Merge PR #1593: tools: Add code complexity linter, gocyclo
This commit is contained in:
commit
777d7bee5a
|
@ -70,6 +70,7 @@ FEATURES
|
|||
* ineffassign
|
||||
* errcheck
|
||||
* unparam
|
||||
* gocyclo
|
||||
* [tools] Add `make format` command to automate fixing misspell and gofmt errors.
|
||||
* [server] Default config now creates a profiler at port 6060, and increase p2p send/recv rates
|
||||
* [tests] Add WaitForNextNBlocksTM helper method
|
||||
|
|
|
@ -324,16 +324,39 @@ func (app *BaseApp) FilterPeerByPubKey(info string) abci.ResponseQuery {
|
|||
return abci.ResponseQuery{}
|
||||
}
|
||||
|
||||
// Implements ABCI.
|
||||
// Delegates to CommitMultiStore if it implements Queryable
|
||||
func (app *BaseApp) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
|
||||
path := strings.Split(req.Path, "/")
|
||||
func splitPath(requestPath string) (path []string) {
|
||||
path = strings.Split(requestPath, "/")
|
||||
// first element is empty string
|
||||
if len(path) > 0 && path[0] == "" {
|
||||
path = path[1:]
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
// Implements ABCI.
|
||||
// Delegates to CommitMultiStore if it implements Queryable
|
||||
func (app *BaseApp) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
|
||||
path := splitPath(req.Path)
|
||||
if len(path) == 0 {
|
||||
msg := "no query path provided"
|
||||
return sdk.ErrUnknownRequest(msg).QueryResult()
|
||||
}
|
||||
switch path[0] {
|
||||
// "/app" prefix for special application queries
|
||||
if len(path) >= 2 && path[0] == "app" {
|
||||
case "app":
|
||||
return handleQueryApp(app, path, req)
|
||||
case "store":
|
||||
return handleQueryStore(app, path, req)
|
||||
case "p2p":
|
||||
return handleQueryP2P(app, path, req)
|
||||
}
|
||||
|
||||
msg := "unknown query path"
|
||||
return sdk.ErrUnknownRequest(msg).QueryResult()
|
||||
}
|
||||
|
||||
func handleQueryApp(app *BaseApp, path []string, req abci.RequestQuery) (res abci.ResponseQuery) {
|
||||
if len(path) >= 2 {
|
||||
var result sdk.Result
|
||||
switch path[1] {
|
||||
case "simulate":
|
||||
|
@ -358,18 +381,24 @@ func (app *BaseApp) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
|
|||
Value: value,
|
||||
}
|
||||
}
|
||||
msg := "Expected second parameter to be either simulate or version, neither was present"
|
||||
return sdk.ErrUnknownRequest(msg).QueryResult()
|
||||
}
|
||||
|
||||
func handleQueryStore(app *BaseApp, path []string, req abci.RequestQuery) (res abci.ResponseQuery) {
|
||||
// "/store" prefix for store queries
|
||||
if len(path) >= 1 && path[0] == "store" {
|
||||
queryable, ok := app.cms.(sdk.Queryable)
|
||||
if !ok {
|
||||
msg := "multistore doesn't support queries"
|
||||
return sdk.ErrUnknownRequest(msg).QueryResult()
|
||||
}
|
||||
req.Path = "/" + strings.Join(path[1:], "/")
|
||||
return queryable.Query(req)
|
||||
queryable, ok := app.cms.(sdk.Queryable)
|
||||
if !ok {
|
||||
msg := "multistore doesn't support queries"
|
||||
return sdk.ErrUnknownRequest(msg).QueryResult()
|
||||
}
|
||||
req.Path = "/" + strings.Join(path[1:], "/")
|
||||
return queryable.Query(req)
|
||||
}
|
||||
|
||||
func handleQueryP2P(app *BaseApp, path []string, req abci.RequestQuery) (res abci.ResponseQuery) {
|
||||
// "/p2p" prefix for p2p queries
|
||||
if len(path) >= 4 && path[0] == "p2p" {
|
||||
if len(path) >= 4 {
|
||||
if path[1] == "filter" {
|
||||
if path[2] == "addr" {
|
||||
return app.FilterPeerByAddrPort(path[3])
|
||||
|
@ -379,9 +408,13 @@ func (app *BaseApp) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
|
|||
// NOTE: this changed in tendermint and we didn't notice...
|
||||
return app.FilterPeerByPubKey(path[3])
|
||||
}
|
||||
} else {
|
||||
msg := "Expected second parameter to be filter"
|
||||
return sdk.ErrUnknownRequest(msg).QueryResult()
|
||||
}
|
||||
}
|
||||
msg := "unknown query path"
|
||||
|
||||
msg := "Expected path is p2p filter <addr|pubkey> <parameter>"
|
||||
return sdk.ErrUnknownRequest(msg).QueryResult()
|
||||
}
|
||||
|
||||
|
@ -472,8 +505,34 @@ func (app *BaseApp) Deliver(tx sdk.Tx) (result sdk.Result) {
|
|||
return app.runTx(runTxModeDeliver, nil, tx)
|
||||
}
|
||||
|
||||
func validateBasicTxMsgs(msgs []sdk.Msg) sdk.Error {
|
||||
if msgs == nil || len(msgs) == 0 {
|
||||
// TODO: probably shouldn't be ErrInternal. Maybe new ErrInvalidMessage, or ?
|
||||
return sdk.ErrInternal("Tx.GetMsgs() must return at least one message in list")
|
||||
}
|
||||
|
||||
for _, msg := range msgs {
|
||||
// Validate the Msg.
|
||||
err := msg.ValidateBasic()
|
||||
if err != nil {
|
||||
err = err.WithDefaultCodespace(sdk.CodespaceRoot)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Returns deliverState if app is in runTxModeDeliver, otherwhise returns checkstate
|
||||
func getState(app *BaseApp, mode runTxMode) *state {
|
||||
if mode == runTxModeCheck || mode == runTxModeSimulate {
|
||||
return app.checkState
|
||||
}
|
||||
return app.deliverState
|
||||
}
|
||||
|
||||
// txBytes may be nil in some cases, eg. in tests.
|
||||
// Also, in the future we may support "internal" transactions.
|
||||
// nolint: gocyclo
|
||||
func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk.Result) {
|
||||
//NOTE: GasWanted should be returned by the AnteHandler.
|
||||
// GasUsed is determined by the GasMeter.
|
||||
|
@ -500,18 +559,9 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk
|
|||
|
||||
// Get the Msg.
|
||||
var msgs = tx.GetMsgs()
|
||||
if msgs == nil || len(msgs) == 0 {
|
||||
// TODO: probably shouldn't be ErrInternal. Maybe new ErrInvalidMessage, or ?
|
||||
return sdk.ErrInternal("Tx.GetMsgs() must return at least one message in list").Result()
|
||||
}
|
||||
|
||||
for _, msg := range msgs {
|
||||
// Validate the Msg.
|
||||
err := msg.ValidateBasic()
|
||||
if err != nil {
|
||||
err = err.WithDefaultCodespace(sdk.CodespaceRoot)
|
||||
return err.Result()
|
||||
}
|
||||
err := validateBasicTxMsgs(msgs)
|
||||
if err != nil {
|
||||
return err.Result()
|
||||
}
|
||||
|
||||
// Run the ante handler.
|
||||
|
@ -526,17 +576,9 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk
|
|||
gasWanted = anteResult.GasWanted
|
||||
}
|
||||
|
||||
// Get the correct cache
|
||||
var msCache sdk.CacheMultiStore
|
||||
if mode == runTxModeCheck || mode == runTxModeSimulate {
|
||||
// CacheWrap app.checkState.ms in case it fails.
|
||||
msCache = app.checkState.CacheMultiStore()
|
||||
ctx = ctx.WithMultiStore(msCache)
|
||||
} else {
|
||||
// CacheWrap app.deliverState.ms in case it fails.
|
||||
msCache = app.deliverState.CacheMultiStore()
|
||||
ctx = ctx.WithMultiStore(msCache)
|
||||
}
|
||||
// Get the correct cache, CacheWrap app.checkState.ms in case it fails.
|
||||
msCache := getState(app, mode).CacheMultiStore()
|
||||
ctx = ctx.WithMultiStore(msCache)
|
||||
|
||||
// accumulate results
|
||||
logs := make([]string, 0, len(msgs))
|
||||
|
|
|
@ -46,6 +46,8 @@ phrase, otherwise, a new key will be generated.`,
|
|||
return cmd
|
||||
}
|
||||
|
||||
// nolint: gocyclo
|
||||
// TODO remove the above when addressing #1446
|
||||
func runAddCmd(cmd *cobra.Command, args []string) error {
|
||||
var kb keys.Keybase
|
||||
var err error
|
||||
|
|
|
@ -60,10 +60,11 @@ Example:
|
|||
}
|
||||
|
||||
func testnetWithConfig(config *cfg.Config, cdc *wire.Codec, appInit AppInit) error {
|
||||
|
||||
outDir := viper.GetString(outputDir)
|
||||
numValidators := viper.GetInt(nValidators)
|
||||
|
||||
// Generate private key, node ID, initial transaction
|
||||
for i := 0; i < viper.GetInt(nValidators); i++ {
|
||||
for i := 0; i < numValidators; i++ {
|
||||
nodeDirName := fmt.Sprintf("%s%d", viper.GetString(nodeDirPrefix), i)
|
||||
nodeDir := filepath.Join(outDir, nodeDirName, "gaiad")
|
||||
clientDir := filepath.Join(outDir, nodeDirName, "gaiacli")
|
||||
|
@ -83,18 +84,9 @@ func testnetWithConfig(config *cfg.Config, cdc *wire.Codec, appInit AppInit) err
|
|||
}
|
||||
|
||||
config.Moniker = nodeDirName
|
||||
|
||||
ip := viper.GetString(startingIPAddress)
|
||||
if len(ip) == 0 {
|
||||
ip, err = externalIP()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
ip, err = calculateIP(ip, i)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ip, err := getIP(i)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
genTxConfig := gc.GenTx{
|
||||
|
@ -112,35 +104,22 @@ func testnetWithConfig(config *cfg.Config, cdc *wire.Codec, appInit AppInit) err
|
|||
|
||||
// Save private key seed words
|
||||
name := fmt.Sprintf("%v.json", "key_seed")
|
||||
writePath := filepath.Join(clientDir)
|
||||
file := filepath.Join(writePath, name)
|
||||
err = cmn.EnsureDir(writePath, 0700)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = cmn.WriteFile(file, cliPrint, 0600)
|
||||
err = writeFile(name, clientDir, cliPrint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Gather gentxs folder
|
||||
name = fmt.Sprintf("%v.json", nodeDirName)
|
||||
writePath = filepath.Join(gentxsDir)
|
||||
file = filepath.Join(writePath, name)
|
||||
err = cmn.EnsureDir(writePath, 0700)
|
||||
err = writeFile(name, gentxsDir, genTxFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = cmn.WriteFile(file, genTxFile, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Generate genesis.json and config.toml
|
||||
chainID := "chain-" + cmn.RandStr(6)
|
||||
for i := 0; i < viper.GetInt(nValidators); i++ {
|
||||
for i := 0; i < numValidators; i++ {
|
||||
|
||||
nodeDirName := fmt.Sprintf("%s%d", viper.GetString(nodeDirPrefix), i)
|
||||
nodeDir := filepath.Join(outDir, nodeDirName, "gaiad")
|
||||
|
@ -165,6 +144,36 @@ func testnetWithConfig(config *cfg.Config, cdc *wire.Codec, appInit AppInit) err
|
|||
return nil
|
||||
}
|
||||
|
||||
func getIP(i int) (ip string, err error) {
|
||||
ip = viper.GetString(startingIPAddress)
|
||||
if len(ip) == 0 {
|
||||
ip, err = externalIP()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
} else {
|
||||
ip, err = calculateIP(ip, i)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
return ip, nil
|
||||
}
|
||||
|
||||
func writeFile(name string, dir string, contents []byte) error {
|
||||
writePath := filepath.Join(dir)
|
||||
file := filepath.Join(writePath, name)
|
||||
err := cmn.EnsureDir(writePath, 0700)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = cmn.WriteFile(file, contents, 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func calculateIP(ip string, i int) (string, error) {
|
||||
ipv4 := net.ParseIP(ip).To4()
|
||||
if ipv4 == nil {
|
||||
|
|
|
@ -149,24 +149,15 @@ func externalIP() (string, error) {
|
|||
return "", err
|
||||
}
|
||||
for _, iface := range ifaces {
|
||||
if iface.Flags&net.FlagUp == 0 {
|
||||
continue // interface down
|
||||
}
|
||||
if iface.Flags&net.FlagLoopback != 0 {
|
||||
continue // loopback interface
|
||||
if skipInterface(iface) {
|
||||
continue
|
||||
}
|
||||
addrs, err := iface.Addrs()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
for _, addr := range addrs {
|
||||
var ip net.IP
|
||||
switch v := addr.(type) {
|
||||
case *net.IPNet:
|
||||
ip = v.IP
|
||||
case *net.IPAddr:
|
||||
ip = v.IP
|
||||
}
|
||||
ip := addrToIP(addr)
|
||||
if ip == nil || ip.IsLoopback() {
|
||||
continue
|
||||
}
|
||||
|
@ -179,3 +170,24 @@ func externalIP() (string, error) {
|
|||
}
|
||||
return "", errors.New("are you connected to the network?")
|
||||
}
|
||||
|
||||
func skipInterface(iface net.Interface) bool {
|
||||
if iface.Flags&net.FlagUp == 0 {
|
||||
return true // interface down
|
||||
}
|
||||
if iface.Flags&net.FlagLoopback != 0 {
|
||||
return true // loopback interface
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func addrToIP(addr net.Addr) net.IP {
|
||||
var ip net.IP
|
||||
switch v := addr.(type) {
|
||||
case *net.IPNet:
|
||||
ip = v.IP
|
||||
case *net.IPAddr:
|
||||
ip = v.IP
|
||||
}
|
||||
return ip
|
||||
}
|
||||
|
|
|
@ -153,6 +153,20 @@ func (st *iavlStore) ReverseIterator(start, end []byte) Iterator {
|
|||
return newIAVLIterator(st.tree.Tree(), start, end, false)
|
||||
}
|
||||
|
||||
// Handle gatest the latest height, if height is 0
|
||||
func getHeight(tree *iavl.VersionedTree, req abci.RequestQuery) int64 {
|
||||
height := req.Height
|
||||
if height == 0 {
|
||||
latest := tree.Version64()
|
||||
if tree.VersionExists(latest - 1) {
|
||||
height = latest - 1
|
||||
} else {
|
||||
height = latest
|
||||
}
|
||||
}
|
||||
return height
|
||||
}
|
||||
|
||||
// Query implements ABCI interface, allows queries
|
||||
//
|
||||
// by default we will return from (latest height -1),
|
||||
|
@ -167,24 +181,17 @@ func (st *iavlStore) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
|
|||
}
|
||||
|
||||
tree := st.tree
|
||||
height := req.Height
|
||||
if height == 0 {
|
||||
latest := tree.Version64()
|
||||
if tree.VersionExists(latest - 1) {
|
||||
height = latest - 1
|
||||
} else {
|
||||
height = latest
|
||||
}
|
||||
}
|
||||
// store the height we chose in the response
|
||||
res.Height = height
|
||||
|
||||
// store the height we chose in the response, with 0 being changed to the
|
||||
// latest height
|
||||
res.Height = getHeight(tree, req)
|
||||
|
||||
switch req.Path {
|
||||
case "/store", "/key": // Get by key
|
||||
key := req.Data // Data holds the key bytes
|
||||
res.Key = key
|
||||
if req.Prove {
|
||||
value, proof, err := tree.GetVersionedWithProof(key, height)
|
||||
value, proof, err := tree.GetVersionedWithProof(key, res.Height)
|
||||
if err != nil {
|
||||
res.Log = err.Error()
|
||||
break
|
||||
|
@ -198,7 +205,7 @@ func (st *iavlStore) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
|
|||
}
|
||||
res.Proof = p
|
||||
} else {
|
||||
_, res.Value = tree.GetVersioned(key, height)
|
||||
_, res.Value = tree.GetVersioned(key, res.Height)
|
||||
}
|
||||
case "/subspace":
|
||||
subspace := req.Data
|
||||
|
|
|
@ -12,6 +12,7 @@ INEFFASSIGN = github.com/gordonklaus/ineffassign
|
|||
MISSPELL = github.com/client9/misspell/cmd/misspell
|
||||
ERRCHECK = github.com/kisielk/errcheck
|
||||
UNPARAM = mvdan.cc/unparam
|
||||
GOCYCLO = github.com/alecthomas/gocyclo
|
||||
|
||||
DEP_CHECK := $(shell command -v dep 2> /dev/null)
|
||||
GOLINT_CHECK := $(shell command -v golint 2> /dev/null)
|
||||
|
@ -21,6 +22,7 @@ INEFFASSIGN_CHECK := $(shell command -v ineffassign 2> /dev/null)
|
|||
MISSPELL_CHECK := $(shell command -v misspell 2> /dev/null)
|
||||
ERRCHECK_CHECK := $(shell command -v errcheck 2> /dev/null)
|
||||
UNPARAM_CHECK := $(shell command -v unparam 2> /dev/null)
|
||||
GOCYCLO_CHECK := $(shell command -v gocyclo 2> /dev/null)
|
||||
|
||||
check_tools:
|
||||
ifndef DEP_CHECK
|
||||
|
@ -63,6 +65,11 @@ ifndef UNPARAM_CHECK
|
|||
else
|
||||
@echo "Found unparam in path."
|
||||
endif
|
||||
ifndef GOCYCLO_CHECK
|
||||
@echo "No gocyclo in path. Install with 'make get_tools'."
|
||||
else
|
||||
@echo "Found gocyclo in path."
|
||||
endif
|
||||
|
||||
get_tools:
|
||||
ifdef DEP_CHECK
|
||||
|
@ -113,6 +120,12 @@ else
|
|||
@echo "Installing unparam"
|
||||
go get -v $(UNPARAM)
|
||||
endif
|
||||
ifdef GOYCLO_CHECK
|
||||
@echo "goyclo is already installed. Run 'make update_tools' to update."
|
||||
else
|
||||
@echo "Installing goyclo"
|
||||
go get -v $(GOCYCLO)
|
||||
endif
|
||||
|
||||
update_tools:
|
||||
@echo "Updating dep"
|
||||
|
@ -131,6 +144,8 @@ update_tools:
|
|||
go get -u -v $(ERRCHECK)
|
||||
@echo "Updating unparam"
|
||||
go get -u -v $(UNPARAM)
|
||||
@echo "Updating goyclo"
|
||||
go get -u -v $(GOCYCLO)
|
||||
|
||||
# To avoid unintended conflicts with file names, always add to .PHONY
|
||||
# unless there is a reason not to.
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
"Linters": {
|
||||
"vet": "go tool vet -composites=false :PATH:LINE:MESSAGE"
|
||||
},
|
||||
"Enable": ["golint", "vet", "ineffassign", "unparam", "unconvert", "misspell"],
|
||||
"Enable": ["golint", "vet", "ineffassign", "unparam", "unconvert", "misspell", "gocyclo"],
|
||||
"Deadline": "500s",
|
||||
"Vendor": true
|
||||
"Vendor": true,
|
||||
"Cyclo": 11
|
||||
}
|
|
@ -66,6 +66,7 @@ const (
|
|||
)
|
||||
|
||||
// NOTE: Don't stringer this, we'll put better messages in later.
|
||||
// nolint: gocyclo
|
||||
func CodeToDefaultMsg(code CodeType) string {
|
||||
switch code {
|
||||
case CodeInternal:
|
||||
|
|
17
types/int.go
17
types/int.go
|
@ -37,6 +37,13 @@ func mod(i *big.Int, i2 *big.Int) *big.Int { return new(big.Int).Mod(i, i2) }
|
|||
|
||||
func neg(i *big.Int) *big.Int { return new(big.Int).Neg(i) }
|
||||
|
||||
func min(i *big.Int, i2 *big.Int) *big.Int {
|
||||
if i.Cmp(i2) == 1 {
|
||||
return new(big.Int).Set(i2)
|
||||
}
|
||||
return new(big.Int).Set(i)
|
||||
}
|
||||
|
||||
// MarshalAmino for custom encoding scheme
|
||||
func marshalAmino(i *big.Int) (string, error) {
|
||||
bz, err := i.MarshalText()
|
||||
|
@ -227,6 +234,11 @@ func (i Int) Neg() (res Int) {
|
|||
return Int{neg(i.i)}
|
||||
}
|
||||
|
||||
// Return the minimum of the ints
|
||||
func MinInt(i1, i2 Int) Int {
|
||||
return Int{min(i1.BigInt(), i2.BigInt())}
|
||||
}
|
||||
|
||||
func (i Int) String() string {
|
||||
return i.i.String()
|
||||
}
|
||||
|
@ -419,6 +431,11 @@ func (i Uint) DivRaw(i2 uint64) Uint {
|
|||
return i.Div(NewUint(i2))
|
||||
}
|
||||
|
||||
// Return the minimum of the Uints
|
||||
func MinUint(i1, i2 Uint) Uint {
|
||||
return Uint{min(i1.BigInt(), i2.BigInt())}
|
||||
}
|
||||
|
||||
// MarshalAmino defines custom encoding scheme
|
||||
func (i Uint) MarshalAmino() (string, error) {
|
||||
if i.i == nil { // Necessary since default Uint initialization has i.i as nil
|
||||
|
|
|
@ -37,6 +37,30 @@ func NewRat(Numerator int64, Denominator ...int64) Rat {
|
|||
}
|
||||
}
|
||||
|
||||
func getNumeratorDenominator(str []string, prec int) (numerator string, denom int64, err Error) {
|
||||
switch len(str) {
|
||||
case 1:
|
||||
if len(str[0]) == 0 {
|
||||
return "", 0, ErrUnknownRequest("not a decimal string")
|
||||
}
|
||||
numerator = str[0]
|
||||
return numerator, 1, nil
|
||||
case 2:
|
||||
if len(str[0]) == 0 || len(str[1]) == 0 {
|
||||
return "", 0, ErrUnknownRequest("not a decimal string")
|
||||
}
|
||||
if len(str[1]) > prec {
|
||||
return "", 0, ErrUnknownRequest("string has too many decimals")
|
||||
}
|
||||
numerator = str[0] + str[1]
|
||||
len := int64(len(str[1]))
|
||||
denom = new(big.Int).Exp(big.NewInt(10), big.NewInt(len), nil).Int64()
|
||||
return numerator, denom, nil
|
||||
default:
|
||||
return "", 0, ErrUnknownRequest("not a decimal string")
|
||||
}
|
||||
}
|
||||
|
||||
// create a rational from decimal string or integer string
|
||||
// precision is the number of values after the decimal point which should be read
|
||||
func NewRatFromDecimal(decimalStr string, prec int) (f Rat, err Error) {
|
||||
|
@ -53,26 +77,9 @@ func NewRatFromDecimal(decimalStr string, prec int) (f Rat, err Error) {
|
|||
|
||||
str := strings.Split(decimalStr, ".")
|
||||
|
||||
var numStr string
|
||||
var denom int64 = 1
|
||||
switch len(str) {
|
||||
case 1:
|
||||
if len(str[0]) == 0 {
|
||||
return f, ErrUnknownRequest("not a decimal string")
|
||||
}
|
||||
numStr = str[0]
|
||||
case 2:
|
||||
if len(str[0]) == 0 || len(str[1]) == 0 {
|
||||
return f, ErrUnknownRequest("not a decimal string")
|
||||
}
|
||||
if len(str[1]) > prec {
|
||||
return f, ErrUnknownRequest("string has too many decimals")
|
||||
}
|
||||
numStr = str[0] + str[1]
|
||||
len := int64(len(str[1]))
|
||||
denom = new(big.Int).Exp(big.NewInt(10), big.NewInt(len), nil).Int64()
|
||||
default:
|
||||
return f, ErrUnknownRequest("not a decimal string")
|
||||
numStr, denom, err := getNumeratorDenominator(str, prec)
|
||||
if err != nil {
|
||||
return f, err
|
||||
}
|
||||
|
||||
num, errConv := strconv.Atoi(numStr)
|
||||
|
|
|
@ -29,45 +29,26 @@ func NewAnteHandler(am AccountMapper, fck FeeCollectionKeeper) sdk.AnteHandler {
|
|||
return ctx, sdk.ErrInternal("tx must be StdTx").Result(), true
|
||||
}
|
||||
|
||||
// Assert that there are signatures.
|
||||
var sigs = stdTx.GetSignatures()
|
||||
if len(sigs) == 0 {
|
||||
return ctx,
|
||||
sdk.ErrUnauthorized("no signers").Result(),
|
||||
true
|
||||
err := validateBasic(stdTx)
|
||||
if err != nil {
|
||||
return ctx, err.Result(), true
|
||||
}
|
||||
|
||||
memo := stdTx.GetMemo()
|
||||
|
||||
if len(memo) > maxMemoCharacters {
|
||||
return ctx,
|
||||
sdk.ErrMemoTooLarge(fmt.Sprintf("maximum number of characters is %d but received %d characters", maxMemoCharacters, len(memo))).Result(),
|
||||
true
|
||||
}
|
||||
sigs := stdTx.GetSignatures()
|
||||
signerAddrs := stdTx.GetSigners()
|
||||
msgs := tx.GetMsgs()
|
||||
|
||||
// set the gas meter
|
||||
ctx = ctx.WithGasMeter(sdk.NewGasMeter(stdTx.Fee.Gas))
|
||||
|
||||
// charge gas for the memo
|
||||
ctx.GasMeter().ConsumeGas(memoCostPerByte*sdk.Gas(len(memo)), "memo")
|
||||
|
||||
msgs := tx.GetMsgs()
|
||||
|
||||
// Assert that number of signatures is correct.
|
||||
var signerAddrs = stdTx.GetSigners()
|
||||
if len(sigs) != len(signerAddrs) {
|
||||
return ctx,
|
||||
sdk.ErrUnauthorized("wrong number of signers").Result(),
|
||||
true
|
||||
}
|
||||
ctx.GasMeter().ConsumeGas(memoCostPerByte*sdk.Gas(len(stdTx.GetMemo())), "memo")
|
||||
|
||||
// Get the sign bytes (requires all account & sequence numbers and the fee)
|
||||
sequences := make([]int64, len(signerAddrs))
|
||||
for i := 0; i < len(signerAddrs); i++ {
|
||||
sequences := make([]int64, len(sigs))
|
||||
accNums := make([]int64, len(sigs))
|
||||
for i := 0; i < len(sigs); i++ {
|
||||
sequences[i] = sigs[i].Sequence
|
||||
}
|
||||
accNums := make([]int64, len(signerAddrs))
|
||||
for i := 0; i < len(signerAddrs); i++ {
|
||||
accNums[i] = sigs[i].AccountNumber
|
||||
}
|
||||
fee := stdTx.Fee
|
||||
|
@ -88,16 +69,15 @@ func NewAnteHandler(am AccountMapper, fck FeeCollectionKeeper) sdk.AnteHandler {
|
|||
}
|
||||
|
||||
// first sig pays the fees
|
||||
if i == 0 {
|
||||
// TODO: min fee
|
||||
if !fee.Amount.IsZero() {
|
||||
ctx.GasMeter().ConsumeGas(deductFeesCost, "deductFees")
|
||||
signerAcc, res = deductFees(signerAcc, fee)
|
||||
if !res.IsOK() {
|
||||
return ctx, res, true
|
||||
}
|
||||
fck.addCollectedFees(ctx, fee.Amount)
|
||||
// TODO: Add min fees
|
||||
// Can this function be moved outside of the loop?
|
||||
if i == 0 && !fee.Amount.IsZero() {
|
||||
ctx.GasMeter().ConsumeGas(deductFeesCost, "deductFees")
|
||||
signerAcc, res = deductFees(signerAcc, fee)
|
||||
if !res.IsOK() {
|
||||
return ctx, res, true
|
||||
}
|
||||
fck.addCollectedFees(ctx, fee.Amount)
|
||||
}
|
||||
|
||||
// Save the account.
|
||||
|
@ -114,6 +94,29 @@ func NewAnteHandler(am AccountMapper, fck FeeCollectionKeeper) sdk.AnteHandler {
|
|||
}
|
||||
}
|
||||
|
||||
// Validate the transaction based on things that don't depend on the context
|
||||
func validateBasic(tx StdTx) (err sdk.Error) {
|
||||
// Assert that there are signatures.
|
||||
sigs := tx.GetSignatures()
|
||||
if len(sigs) == 0 {
|
||||
return sdk.ErrUnauthorized("no signers")
|
||||
}
|
||||
|
||||
// Assert that number of signatures is correct.
|
||||
var signerAddrs = tx.GetSigners()
|
||||
if len(sigs) != len(signerAddrs) {
|
||||
return sdk.ErrUnauthorized("wrong number of signers")
|
||||
}
|
||||
|
||||
memo := tx.GetMemo()
|
||||
if len(memo) > maxMemoCharacters {
|
||||
return sdk.ErrMemoTooLarge(
|
||||
fmt.Sprintf("maximum number of characters is %d but received %d characters",
|
||||
maxMemoCharacters, len(memo)))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// verify the signature and increment the sequence.
|
||||
// if the account doesn't have a pubkey, set it.
|
||||
func processSig(
|
||||
|
|
|
@ -369,6 +369,8 @@ func queryVoteHandlerFn(cdc *wire.Codec) http.HandlerFunc {
|
|||
}
|
||||
}
|
||||
|
||||
// nolint: gocyclo
|
||||
// todo: Split this functionality into helper functions to remove the above
|
||||
func queryProposalsWithParameterFn(cdc *wire.Codec) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
bechVoterAddr := r.URL.Query().Get(RestVoter)
|
||||
|
|
|
@ -86,6 +86,8 @@ func (c relayCommander) runIBCRelay(cmd *cobra.Command, args []string) {
|
|||
c.loop(fromChainID, fromChainNode, toChainID, toChainNode)
|
||||
}
|
||||
|
||||
// This is nolinted as someone is in the process of refactoring this to remove the goto
|
||||
// nolint: gocyclo
|
||||
func (c relayCommander) loop(fromChainID, fromChainNode, toChainID,
|
||||
toChainNode string) {
|
||||
|
||||
|
|
|
@ -208,6 +208,8 @@ func GetCmdBeginRedelegate(storeName string, cdc *wire.Codec) *cobra.Command {
|
|||
return cmd
|
||||
}
|
||||
|
||||
// nolint: gocyclo
|
||||
// TODO: Make this pass gocyclo linting
|
||||
func getShares(storeName string, cdc *wire.Codec, sharesAmountStr, sharesPercentStr string,
|
||||
delegatorAddr, validatorAddr sdk.Address) (sharesAmount sdk.Rat, err error) {
|
||||
|
||||
|
|
|
@ -65,6 +65,8 @@ type EditDelegationsBody struct {
|
|||
CompleteRedelegates []msgCompleteRedelegateInput `json:"complete_redelegates"`
|
||||
}
|
||||
|
||||
// nolint: gocyclo
|
||||
// TODO: Split this up into several smaller functions, and remove the above nolint
|
||||
func editDelegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx context.CoreContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var m EditDelegationsBody
|
||||
|
|
|
@ -342,6 +342,7 @@ func checkValidatorSetup(t *testing.T, pool types.Pool, initialTotalTokens, init
|
|||
}
|
||||
|
||||
// Checks that The inflation will correctly increase or decrease after an update to the pool
|
||||
// nolint: gocyclo
|
||||
func checkInflation(t *testing.T, pool types.Pool, previousInflation, updatedInflation sdk.Rat, msg string) {
|
||||
inflationChange := updatedInflation.Sub(previousInflation)
|
||||
|
||||
|
|
|
@ -81,10 +81,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in
|
|||
}
|
||||
|
||||
// Cannot decrease balance below zero
|
||||
sharesToRemove := remainingSlashAmount
|
||||
if sharesToRemove.GT(validator.PoolShares.Amount.RoundInt()) {
|
||||
sharesToRemove = validator.PoolShares.Amount.RoundInt()
|
||||
}
|
||||
sharesToRemove := sdk.MinInt(remainingSlashAmount, validator.PoolShares.Amount.RoundInt())
|
||||
|
||||
// Get the current pool
|
||||
pool := k.GetPool(ctx)
|
||||
|
@ -163,10 +160,7 @@ func (k Keeper) slashUnbondingDelegation(ctx sdk.Context, unbondingDelegation ty
|
|||
// Possible since the unbonding delegation may already
|
||||
// have been slashed, and slash amounts are calculated
|
||||
// according to stake held at time of infraction
|
||||
unbondingSlashAmount := slashAmount
|
||||
if unbondingSlashAmount.GT(unbondingDelegation.Balance.Amount) {
|
||||
unbondingSlashAmount = unbondingDelegation.Balance.Amount
|
||||
}
|
||||
unbondingSlashAmount := sdk.MinInt(slashAmount, unbondingDelegation.Balance.Amount)
|
||||
|
||||
// Update unbonding delegation if necessary
|
||||
if !unbondingSlashAmount.IsZero() {
|
||||
|
@ -208,10 +202,7 @@ func (k Keeper) slashRedelegation(ctx sdk.Context, validator types.Validator, re
|
|||
// Possible since the redelegation may already
|
||||
// have been slashed, and slash amounts are calculated
|
||||
// according to stake held at time of infraction
|
||||
redelegationSlashAmount := slashAmount
|
||||
if redelegationSlashAmount.GT(redelegation.Balance.Amount) {
|
||||
redelegationSlashAmount = redelegation.Balance.Amount
|
||||
}
|
||||
redelegationSlashAmount := sdk.MinInt(slashAmount, redelegation.Balance.Amount)
|
||||
|
||||
// Update redelegation if necessary
|
||||
if !redelegationSlashAmount.IsZero() {
|
||||
|
|
|
@ -194,6 +194,8 @@ func (k Keeper) ClearTendermintUpdates(ctx sdk.Context) {
|
|||
// perfom all the nessisary steps for when a validator changes its power
|
||||
// updates all validator stores as well as tendermint update store
|
||||
// may kick out validators if new validator is entering the bonded validator group
|
||||
// nolint: gocyclo
|
||||
// TODO: Remove above nolint, function needs to be simplified
|
||||
func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) types.Validator {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
pool := k.GetPool(ctx)
|
||||
|
@ -284,6 +286,8 @@ func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) type
|
|||
// GetValidators.
|
||||
//
|
||||
// Optionally also return the validator from a retrieve address if the validator has been bonded
|
||||
// nolint: gocyclo
|
||||
// TODO: Remove the above golint
|
||||
func (k Keeper) UpdateBondedValidators(ctx sdk.Context,
|
||||
affectedValidator types.Validator) (updatedVal types.Validator) {
|
||||
|
||||
|
@ -422,6 +426,11 @@ func (k Keeper) UpdateBondedValidatorsFull(ctx sdk.Context) {
|
|||
iterator.Close()
|
||||
|
||||
// perform the actual kicks
|
||||
kickOutValidators(k, ctx, toKickOut)
|
||||
return
|
||||
}
|
||||
|
||||
func kickOutValidators(k Keeper, ctx sdk.Context, toKickOut map[string]byte) {
|
||||
for key := range toKickOut {
|
||||
ownerAddr := []byte(key)
|
||||
validator, found := k.GetValidator(ctx, ownerAddr)
|
||||
|
@ -430,7 +439,6 @@ func (k Keeper) UpdateBondedValidatorsFull(ctx sdk.Context) {
|
|||
}
|
||||
k.unbondValidator(ctx, validator)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// perform all the store operations for when a validator status becomes unbonded
|
||||
|
|
Loading…
Reference in New Issue