├── README.md ├── README_kr.md ├── config.toml ├── config └── config.go ├── exporter ├── exporter.go └── metric │ ├── address.go │ ├── metric.go │ └── types.go ├── getData ├── rest │ ├── balances.go │ ├── delegations.go │ ├── gov.go │ ├── inflation.go │ ├── rest.go │ ├── rewardsAndCommission.go │ ├── stakingPool.go │ ├── validators.go │ └── validatorsets.go └── rpc │ ├── commit.go │ └── rpc.go ├── go.mod ├── go.sum ├── main.go └── utils ├── address.go └── converter.go /README.md: -------------------------------------------------------------------------------- 1 | Please use a new repositorie: https://github.com/node-a-team/Cosmos-IE 2 | -------------------------------------------------------------------------------- /README_kr.md: -------------------------------------------------------------------------------- 1 | # cosmos-validator_exporter :satellite: 2 | ![CreatePlan](https://img.shields.io/badge/relase-v0.3.0-red) 3 | ![CreatePlan](https://img.shields.io/badge/go-1.13.1%2B-blue) 4 | ![CreatePlan](https://img.shields.io/badge/license-Apache--2.0-green) 5 | 6 | Cosmos 검증인을 위한 Prometheus exporter 7 | 8 | 9 | ## Introduction 10 | Tendermint의 기본 Prometheus exporter(localhost:26660)에서 제공되지 않는 부분, 특별히 검증인의 정보를 모니터링하기 위한 exporter 11 | -------------------------------------------------------------------------------- /config.toml: -------------------------------------------------------------------------------- 1 | # TOML Document for Cosmos-Validator Exporter(Pometheus & Grafana) 2 | 3 | title = "TOML Document" 4 | 5 | [Servers] 6 | [Servers.addr] 7 | rpc = "localhost:26657" 8 | rest = "localhost:1317" 9 | 10 | [Validator] 11 | operatorAddr = "cosmosvaloper14l0fp639yudfl46zauvv8rkzjgd4u0zk2aseys" 12 | 13 | [Options] 14 | listenPort = "26661" 15 | -------------------------------------------------------------------------------- /config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/BurntSushi/toml" 7 | 8 | rpc "github.com/node-a-team/cosmos-validator_exporter/getData/rpc" 9 | rest "github.com/node-a-team/cosmos-validator_exporter/getData/rest" 10 | ) 11 | 12 | const ( 13 | ) 14 | 15 | var ( 16 | ConfigPath string 17 | Config configType 18 | ) 19 | 20 | 21 | type configType struct { 22 | 23 | Title string `json:"title"` 24 | 25 | Servers struct { 26 | Addr struct { 27 | RPC string `json:"rpc"` 28 | REST string `json:"rest"` 29 | } 30 | } 31 | 32 | Validator struct { 33 | OperatorAddr string `json:"operatorAddr"` 34 | } 35 | 36 | Options struct { 37 | ListenPort string `json:"listenPort"` 38 | } 39 | } 40 | 41 | 42 | func Init() string { 43 | 44 | Config = readConfig() 45 | 46 | rpc.Addr = Config.Servers.Addr.RPC 47 | rest.Addr = Config.Servers.Addr.REST 48 | 49 | rest.OperAddr = Config.Validator.OperatorAddr 50 | 51 | return Config.Options.ListenPort 52 | } 53 | 54 | func readConfig() configType { 55 | 56 | var config configType 57 | 58 | if _, err := toml.DecodeFile(ConfigPath +"/config.toml", &config); err != nil{ 59 | 60 | log.Fatal("Config file is missing: ", config) 61 | } 62 | 63 | return config 64 | 65 | } 66 | -------------------------------------------------------------------------------- /exporter/exporter.go: -------------------------------------------------------------------------------- 1 | package exporter 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | "go.uber.org/zap" 7 | 8 | rpc "github.com/node-a-team/cosmos-validator_exporter/getData/rpc" 9 | rest "github.com/node-a-team/cosmos-validator_exporter/getData/rest" 10 | metric "github.com/node-a-team/cosmos-validator_exporter/exporter/metric" 11 | utils "github.com/node-a-team/cosmos-validator_exporter/utils" 12 | 13 | "github.com/prometheus/client_golang/prometheus" 14 | ) 15 | 16 | var ( 17 | previousBlockHeight int64 18 | 19 | ) 20 | 21 | func Start(log *zap.Logger) { 22 | 23 | gaugesNamespaceList := metric.GaugesNamespaceList 24 | 25 | var gauges []prometheus.Gauge = make([]prometheus.Gauge, len(gaugesNamespaceList)) 26 | var gaugesDenom []prometheus.Gauge = make([]prometheus.Gauge, len(metric.DenomList)*3) // wallet, rewards, commission 27 | 28 | 29 | // nomal guages 30 | for i := 0; i < len(gaugesNamespaceList); i++ { 31 | gauges[i] = metric.NewGauge("exporter", gaugesNamespaceList[i], "") 32 | prometheus.MustRegister(gauges[i]) 33 | } 34 | 35 | 36 | // denom gagues 37 | count := 0 38 | for i := 0; i < len(metric.DenomList)*3; i += 3 { 39 | gaugesDenom[i] = metric.NewGauge("exporter_balances", metric.DenomList[count], "") 40 | gaugesDenom[i+1] = metric.NewGauge("exporter_commission", metric.DenomList[count], "") 41 | gaugesDenom[i+2] = metric.NewGauge("exporter_rewards", metric.DenomList[count], "") 42 | prometheus.MustRegister(gaugesDenom[i]) 43 | prometheus.MustRegister(gaugesDenom[i+1]) 44 | prometheus.MustRegister(gaugesDenom[i+2]) 45 | 46 | count++ 47 | } 48 | 49 | 50 | // labels 51 | labels := []string{"chainId", "moniker", "operatorAddress", "accountAddress", "consHexAddress"} 52 | gaugesForLabel := metric.NewCounterVec("exporter", "labels", "", labels) 53 | 54 | prometheus.MustRegister(gaugesForLabel) 55 | 56 | 57 | for { 58 | func() { 59 | defer func() { 60 | 61 | if r := recover(); r != nil { 62 | //Error Log 63 | } 64 | 65 | time.Sleep(500 * time.Millisecond) 66 | 67 | }() 68 | 69 | 70 | currentBlockHeight := rpc.BlockHeight() 71 | 72 | if previousBlockHeight != currentBlockHeight { 73 | 74 | log.Info("RPC-Server", zap.Bool("Success", true), zap.String("err", "nil"), zap.String("Get Data", "Block Height: " +fmt.Sprint(currentBlockHeight))) 75 | 76 | 77 | restData, consHexAddr := rest.GetData(currentBlockHeight, log) 78 | rpcData := rpc.GetData(currentBlockHeight, consHexAddr, log) 79 | 80 | metric.SetMetric(currentBlockHeight, restData, rpcData, log) 81 | 82 | metricData := metric.GetMetric() 83 | denomList := metric.GetDenomList() 84 | 85 | count := 0 86 | for i := 0; i < len(denomList); i++ { 87 | 88 | for _, value := range metricData.Validator.Account.Balances { 89 | if value.Denom == denomList[i] { 90 | gaugesDenom[count].Set(utils.StringToFloat64(value.Amount)) 91 | count++ 92 | } 93 | } 94 | for _, value := range metricData.Validator.Account.Commission { 95 | if value.Denom == denomList[i] { 96 | gaugesDenom[count].Set(utils.StringToFloat64(value.Amount)) 97 | count++ 98 | } 99 | } 100 | for _, value := range metricData.Validator.Account.Rewards { 101 | if value.Denom == denomList[i] { 102 | gaugesDenom[count].Set(utils.StringToFloat64(value.Amount)) 103 | count++ 104 | } 105 | } 106 | } 107 | 108 | 109 | gaugesValue := [...]float64{ 110 | float64(metricData.Network.BlockHeight), 111 | 112 | metricData.Network.Staking.NotBondedTokens, 113 | metricData.Network.Staking.BondedTokens, 114 | metricData.Network.Staking.TotalSupply, 115 | metricData.Network.Staking.BondedRatio, 116 | 117 | metricData.Network.Gov.TotalProposalCount, 118 | metricData.Network.Gov.VotingProposalCount, 119 | 120 | metricData.Validator.VotingPower, 121 | metricData.Validator.MinSelfDelegation, 122 | metricData.Validator.JailStatus, 123 | 124 | metricData.Validator.Proposer.Ranking, 125 | metricData.Validator.Proposer.Status, 126 | 127 | metricData.Validator.Delegation.Shares, 128 | metricData.Validator.Delegation.Ratio, 129 | metricData.Validator.Delegation.DelegatorCount, 130 | metricData.Validator.Delegation.Self, 131 | 132 | metricData.Validator.Commission.Rate, 133 | metricData.Validator.Commission.MaxRate, 134 | metricData.Validator.Commission.MaxChangeRate, 135 | metricData.Validator.Commit.VoteType, 136 | metricData.Validator.Commit.PrecommitStatus, 137 | 138 | metricData.Network.Minting.Inflation, 139 | metricData.Network.Minting.ActualInflation, 140 | } 141 | 142 | for i := 0; i < len(gaugesNamespaceList); i++ { 143 | gauges[i].Set(gaugesValue[i]) 144 | } 145 | 146 | 147 | gaugesForLabel.WithLabelValues(metricData.Network.ChainID, 148 | metricData.Validator.Moniker, 149 | metricData.Validator.Address.Operator, 150 | metricData.Validator.Address.Account, 151 | metricData.Validator.Address.ConsensusHex, 152 | ).Add(0) 153 | 154 | } 155 | 156 | previousBlockHeight = currentBlockHeight 157 | }() 158 | } 159 | } 160 | 161 | 162 | -------------------------------------------------------------------------------- /exporter/metric/address.go: -------------------------------------------------------------------------------- 1 | package metric 2 | 3 | import ( 4 | "fmt" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | ) 8 | 9 | var ( 10 | 11 | ) 12 | 13 | func GetAccAddrFromOperAddr(operAddr string) string { 14 | 15 | // Get HexAddress 16 | hexAddr, err := sdk.ValAddressFromBech32(operAddr) 17 | if err != nil { 18 | // Error 19 | } 20 | 21 | accAddr, err := sdk.AccAddressFromHex(fmt.Sprint(hexAddr)) 22 | if err != nil { 23 | // Error 24 | } 25 | 26 | return accAddr.String() 27 | } 28 | -------------------------------------------------------------------------------- /exporter/metric/metric.go: -------------------------------------------------------------------------------- 1 | package metric 2 | 3 | import ( 4 | "go.uber.org/zap" 5 | 6 | rest "github.com/node-a-team/cosmos-validator_exporter/getData/rest" 7 | rpc "github.com/node-a-team/cosmos-validator_exporter/getData/rpc" 8 | cfg "github.com/node-a-team/cosmos-validator_exporter/config" 9 | utils "github.com/node-a-team/cosmos-validator_exporter/utils" 10 | ) 11 | 12 | var ( 13 | metricData metric 14 | 15 | DenomList = []string{"uatom"} 16 | GaugesNamespaceList = [...]string{"blockHeight", 17 | "notBondedTokens", 18 | "bondedTokens", 19 | "totalSupply", 20 | "bondedRatio", 21 | "totalProposalCount", 22 | "votingProposalCount", 23 | "votingPower", 24 | "minSelfDelegation", 25 | "jailStatus", 26 | "proposerRanking", 27 | "proposerStatus", 28 | "delegationShares", 29 | "delegationRatio", 30 | "delegatorCount", 31 | "delegationSelf", 32 | "commissionRate", 33 | "commissionMaxRate", 34 | "commissionMaxChangeRate", 35 | "commitVoteType", 36 | "precommitStatus", 37 | "inflation", 38 | "actualInflation", 39 | } 40 | ) 41 | 42 | type metric struct { 43 | 44 | Network struct { 45 | ChainID string 46 | BlockHeight int64 47 | PrecommitRate float64 48 | 49 | Staking struct { 50 | NotBondedTokens float64 51 | BondedTokens float64 52 | TotalSupply float64 53 | BondedRatio float64 54 | } 55 | 56 | Minting struct { 57 | Inflation float64 58 | ActualInflation float64 59 | } 60 | 61 | Gov struct{ 62 | TotalProposalCount float64 63 | VotingProposalCount float64 64 | } 65 | } 66 | 67 | Validator struct { 68 | Moniker string 69 | VotingPower float64 70 | MinSelfDelegation float64 71 | JailStatus float64 72 | 73 | 74 | 75 | Address struct { 76 | Account string 77 | Operator string 78 | ConsensusHex string 79 | } 80 | Proposer struct { 81 | Ranking float64 82 | Status float64 83 | } 84 | 85 | Delegation struct { 86 | Shares float64 87 | Ratio float64 88 | DelegatorCount float64 89 | Self float64 90 | } 91 | 92 | Commission struct { 93 | Rate float64 94 | MaxRate float64 95 | MaxChangeRate float64 96 | } 97 | 98 | Account struct { 99 | Balances []rest.Coin 100 | Commission []rest.Coin 101 | Rewards []rest.Coin 102 | } 103 | 104 | Commit struct { 105 | VoteType float64 106 | PrecommitStatus float64 107 | } 108 | 109 | } 110 | } 111 | 112 | 113 | 114 | func SetMetric(currentBlock int64, restData *rest.RESTData, rpcData *rpc.RPCData, log *zap.Logger) { 115 | 116 | operAddr := cfg.Config.Validator.OperatorAddr 117 | consPubKey := restData.Validators.ConsPubKey 118 | consAddr := restData.Validatorsets[consPubKey][0] 119 | 120 | //// network 121 | metricData.Network.ChainID = rpcData.Commit.ChainId 122 | metricData.Network.BlockHeight = currentBlock 123 | 124 | metricData.Network.Staking.NotBondedTokens = utils.StringToFloat64(restData.StakingPool.Result.Not_bonded_tokens) 125 | metricData.Network.Staking.BondedTokens = utils.StringToFloat64(restData.StakingPool.Result.Bonded_tokens) 126 | metricData.Network.Staking.TotalSupply = restData.StakingPool.Result.Total_supply 127 | metricData.Network.Staking.BondedRatio = metricData.Network.Staking.BondedTokens / metricData.Network.Staking.TotalSupply 128 | 129 | // minting 130 | metricData.Network.Minting.Inflation = restData.Inflation 131 | metricData.Network.Minting.ActualInflation = metricData.Network.Minting.Inflation / metricData.Network.Staking.BondedRatio 132 | 133 | // gov 134 | metricData.Network.Gov.TotalProposalCount = restData.Gov.TotalProposalCount 135 | metricData.Network.Gov.VotingProposalCount = restData.Gov.VotingProposalCount 136 | 137 | 138 | //// validator 139 | metricData.Validator.Moniker = restData.Validators.Description.Moniker 140 | metricData.Validator.VotingPower = utils.StringToFloat64(restData.Validatorsets[consPubKey][1]) 141 | metricData.Validator.MinSelfDelegation = utils.StringToFloat64(restData.Validators.MinSelfDelegation) 142 | metricData.Validator.JailStatus = utils.BoolToFloat64(restData.Validators.Jailed) 143 | 144 | // address 145 | metricData.Validator.Address.Operator = operAddr 146 | metricData.Validator.Address.Account = utils.GetAccAddrFromOperAddr(operAddr, log) 147 | metricData.Validator.Address.ConsensusHex = utils.Bech32AddrToHexAddr(consAddr, log) 148 | 149 | // proposer 150 | metricData.Validator.Proposer.Ranking = utils.StringToFloat64(restData.Validatorsets[consPubKey][3]) 151 | metricData.Validator.Proposer.Status = rpcData.Commit.ValidatorProposingStatus 152 | 153 | // delegation 154 | metricData.Validator.Delegation.Shares = utils.StringToFloat64(restData.Validators.DelegatorShares) 155 | metricData.Validator.Delegation.Ratio = metricData.Validator.Delegation.Shares / metricData.Network.Staking.BondedTokens 156 | metricData.Validator.Delegation.DelegatorCount = restData.Delegations.DelegationCount 157 | metricData.Validator.Delegation.Self = restData.Delegations.SelfDelegation 158 | 159 | // commission 160 | metricData.Validator.Commission.Rate = utils.StringToFloat64(restData.Validators.Commission.Commission_rates.Rate) 161 | metricData.Validator.Commission.MaxRate = utils.StringToFloat64(restData.Validators.Commission.Commission_rates.Max_rate) 162 | metricData.Validator.Commission.MaxChangeRate = utils.StringToFloat64(restData.Validators.Commission.Commission_rates.Max_change_rate) 163 | 164 | // account 165 | metricData.Validator.Account.Balances = restData.Balances 166 | metricData.Validator.Account.Commission = restData.Commission 167 | metricData.Validator.Account.Rewards = restData.Rewards 168 | 169 | // commit 170 | metricData.Validator.Commit.VoteType = rpcData.Commit.VoteType 171 | metricData.Validator.Commit.PrecommitStatus = rpcData.Commit.ValidatorPrecommitStatus 172 | 173 | 174 | 175 | } 176 | 177 | func GetMetric() *metric { 178 | 179 | return &metricData 180 | } 181 | 182 | func GetDenomList() []string { 183 | return DenomList 184 | } 185 | -------------------------------------------------------------------------------- /exporter/metric/types.go: -------------------------------------------------------------------------------- 1 | package metric 2 | 3 | import ( 4 | "github.com/prometheus/client_golang/prometheus" 5 | ) 6 | 7 | var ( 8 | 9 | ) 10 | 11 | func NewGauge(nameSpace string, name string, help string) prometheus.Gauge { 12 | result := prometheus.NewGauge( 13 | prometheus.GaugeOpts{ 14 | Namespace: "" + nameSpace, 15 | Name: "" + name, 16 | Help: "" + help, 17 | }, 18 | ) 19 | 20 | return result 21 | } 22 | 23 | func NewCounterVec(nameSpace string, name string, help string, labels []string) prometheus.CounterVec { 24 | result := prometheus.NewCounterVec( 25 | prometheus.CounterOpts{ 26 | Namespace: "" + nameSpace, 27 | Name: "" + name, 28 | Help: "" + help, 29 | }, 30 | labels, 31 | ) 32 | return *result 33 | } 34 | 35 | -------------------------------------------------------------------------------- /getData/rest/balances.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "strings" 5 | "go.uber.org/zap" 6 | "encoding/json" 7 | ) 8 | 9 | type balances struct { 10 | Height string `json:"height"` 11 | Result []Coin 12 | } 13 | 14 | type Coin struct { 15 | Denom string 16 | Amount string 17 | } 18 | 19 | func getBalances(accAddr string, log *zap.Logger) []Coin { 20 | 21 | var b balances 22 | 23 | res, _ := runRESTCommand("/bank/balances/" +accAddr) 24 | json.Unmarshal(res, &b) 25 | // log 26 | if strings.Contains(string(res), "not found") { 27 | // handle error 28 | log.Fatal("REST-Server", zap.Bool("Success", false), zap.String("err", string(res),)) 29 | } else { 30 | log.Info("REST-Server", zap.Bool("Success", true), zap.String("err", "nil"), zap.String("Get Data", "Staking Pool"),) 31 | } 32 | 33 | return b.Result 34 | } 35 | -------------------------------------------------------------------------------- /getData/rest/delegations.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "strings" 5 | "go.uber.org/zap" 6 | "encoding/json" 7 | utils "github.com/node-a-team/cosmos-validator_exporter/utils" 8 | ) 9 | 10 | type delegations struct { 11 | Height string `json:"height"` 12 | Result []delegation 13 | } 14 | 15 | type delegation struct { 16 | Delegator_address string `json:"delegator_address"` 17 | Validator_address string `json:"validator_address"` 18 | Shares string `json:"shares"` 19 | Balance string `json:"balance"` 20 | } 21 | 22 | type delegationInfo struct { 23 | DelegationCount float64 24 | SelfDelegation float64 25 | } 26 | 27 | func getDelegations(accAddr string, log *zap.Logger) delegationInfo { 28 | 29 | var d delegations 30 | var dInfo delegationInfo 31 | 32 | res, _ := runRESTCommand("/staking/validators/" +OperAddr +"/delegations") 33 | json.Unmarshal(res, &d) 34 | // log 35 | if strings.Contains(string(res), "not found") { 36 | // handle error 37 | log.Fatal("REST-Server", zap.Bool("Success", false), zap.String("err", string(res),)) 38 | } else { 39 | log.Info("REST-Server", zap.Bool("Success", true), zap.String("err", "nil"), zap.String("Get Data", "Delegations"),) 40 | } 41 | 42 | dInfo.DelegationCount = float64(len(d.Result)) 43 | 44 | for _, value := range d.Result { 45 | if accAddr == value.Delegator_address { 46 | dInfo.SelfDelegation = utils.StringToFloat64(value.Shares) 47 | } 48 | } 49 | 50 | return dInfo 51 | } 52 | -------------------------------------------------------------------------------- /getData/rest/gov.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "strings" 5 | "go.uber.org/zap" 6 | "encoding/json" 7 | ) 8 | 9 | type govInfo struct { 10 | TotalProposalCount float64 11 | VotingProposalCount float64 12 | } 13 | 14 | 15 | type gov struct { 16 | Height string 17 | Result []proposal 18 | } 19 | 20 | type proposal struct { 21 | Content struct { 22 | Type string 23 | Value struct { 24 | Title string 25 | Description string 26 | } 27 | 28 | } 29 | Id string 30 | Proposal_status string 31 | Final_tally_result struct { 32 | Yes string 33 | Abstain string 34 | No string 35 | No_with_veto string 36 | } 37 | 38 | Submit_time string 39 | Deposit_end_time string 40 | Total_deposit string 41 | Voting_start_time string 42 | Voting_end_time string 43 | 44 | } 45 | 46 | func getGovInfo(log *zap.Logger) govInfo { 47 | 48 | var g gov 49 | var gi govInfo 50 | 51 | votingCount := 0 52 | 53 | res, _ := runRESTCommand("/gov/proposals") 54 | json.Unmarshal(res, &g) 55 | // log 56 | if strings.Contains(string(res), "not found") { 57 | // handle error 58 | log.Fatal("REST-Server", zap.Bool("Success", false), zap.String("err", string(res),)) 59 | } else { 60 | log.Info("REST-Server", zap.Bool("Success", true), zap.String("err", "nil"), zap.String("Get Data", "Governance"),) 61 | } 62 | 63 | for _, value := range g.Result { 64 | if value.Proposal_status == "VotingPeriod" { 65 | votingCount++ 66 | } 67 | } 68 | 69 | gi.TotalProposalCount = float64(len(g.Result)) 70 | gi.VotingProposalCount = float64(votingCount) 71 | 72 | return gi 73 | } 74 | -------------------------------------------------------------------------------- /getData/rest/inflation.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "strings" 5 | "go.uber.org/zap" 6 | "encoding/json" 7 | 8 | utils "github.com/node-a-team/cosmos-validator_exporter/utils" 9 | ) 10 | 11 | type inflation struct { 12 | Height string `json:"height"` 13 | Result string `json:"result"` 14 | } 15 | 16 | func getInflation(log *zap.Logger) float64 { 17 | 18 | var i inflation 19 | 20 | res, _ := runRESTCommand("/minting/inflation") 21 | json.Unmarshal(res, &i) 22 | 23 | // log 24 | if strings.Contains(string(res), "not found") { 25 | // handle error 26 | log.Fatal("REST-Server", zap.Bool("Success", false), zap.String("err", string(res),)) 27 | } else { 28 | log.Info("REST-Server", zap.Bool("Success", true), zap.String("err", "nil"), zap.String("Get Data", "Inflation"),) 29 | } 30 | 31 | return utils.StringToFloat64(i.Result) 32 | } 33 | -------------------------------------------------------------------------------- /getData/rest/rest.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "go.uber.org/zap" 5 | "os/exec" 6 | 7 | utils "github.com/node-a-team/cosmos-validator_exporter/utils" 8 | ) 9 | 10 | var ( 11 | Addr string 12 | OperAddr string 13 | ) 14 | 15 | 16 | type RESTData struct { 17 | 18 | BlockHeight int64 19 | StakingPool stakingPool 20 | 21 | Validatorsets map[string][]string 22 | Validators validator 23 | Delegations delegationInfo 24 | Balances []Coin 25 | Rewards []Coin 26 | Commission []Coin 27 | Inflation float64 28 | 29 | Gov govInfo 30 | } 31 | 32 | func newRESTData(blockHeight int64) *RESTData { 33 | 34 | rd := &RESTData { 35 | BlockHeight: blockHeight, 36 | Validatorsets: make(map[string][]string), 37 | } 38 | 39 | return rd 40 | } 41 | 42 | func GetData(blockHeight int64, log *zap.Logger) (*RESTData, string) { 43 | 44 | 45 | accAddr := utils.GetAccAddrFromOperAddr(OperAddr, log) 46 | 47 | rd := newRESTData(blockHeight) 48 | rd.StakingPool = getStakingPool(log) 49 | rd.Inflation = getInflation(log) 50 | 51 | rd.Validatorsets = getValidatorsets(blockHeight, log) 52 | rd.Validators = getValidators(log) 53 | rd.Delegations = getDelegations(accAddr, log) 54 | rd.Balances = getBalances(accAddr, log) 55 | rd.Rewards, rd.Commission = getRewardsAndCommisson(log) 56 | 57 | rd.Gov = getGovInfo(log) 58 | 59 | consHexAddr := utils.Bech32AddrToHexAddr(rd.Validatorsets[rd.Validators.ConsPubKey][0], log) 60 | return rd, consHexAddr 61 | } 62 | 63 | func runRESTCommand(str string) ([]uint8, error) { 64 | cmd := "curl -s -XGET " +Addr +str +" -H \"accept:application/json\"" 65 | out, err := exec.Command("/bin/bash", "-c", cmd).Output() 66 | // fmt.Println(cmd) 67 | 68 | return out, err 69 | } 70 | -------------------------------------------------------------------------------- /getData/rest/rewardsAndCommission.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "strings" 5 | "go.uber.org/zap" 6 | "encoding/json" 7 | ) 8 | 9 | type rewardsAndCommisson struct { 10 | 11 | Height string `json:"height"` 12 | Result struct { 13 | Operator_Address string `"json:"operator_address"` 14 | Self_bond_rewards []Coin `"json:"self_bond_rewards"` 15 | Val_commission []Coin `"json:"val_commission"` 16 | } 17 | 18 | } 19 | 20 | func getRewardsAndCommisson(log *zap.Logger) ([]Coin, []Coin) { 21 | 22 | var rc rewardsAndCommisson 23 | 24 | res, _ := runRESTCommand("/distribution/validators/" +OperAddr) 25 | json.Unmarshal(res, &rc) 26 | // log 27 | if strings.Contains(string(res), "not found") { 28 | // handle error 29 | log.Fatal("REST-Server", zap.Bool("Success", false), zap.String("err", string(res),)) 30 | } else { 31 | log.Info("REST-Server", zap.Bool("Success", true), zap.String("err", "nil"), zap.String("Get Data", "Rewards&Commission"),) 32 | } 33 | 34 | return rc.Result.Self_bond_rewards, rc.Result.Val_commission 35 | } 36 | -------------------------------------------------------------------------------- /getData/rest/stakingPool.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "strings" 5 | "go.uber.org/zap" 6 | "encoding/json" 7 | 8 | utils "github.com/node-a-team/cosmos-validator_exporter/utils" 9 | ) 10 | 11 | type stakingPool struct { 12 | Height string `json:"height"` 13 | Result struct { 14 | Not_bonded_tokens string `json:"not_bonded_tokens"` 15 | Bonded_tokens string `json:"bonded_tokens"` 16 | Total_supply float64 17 | } 18 | } 19 | 20 | type totalSupply struct { 21 | Height string `json:"height"` 22 | Result string `json:"result"` 23 | } 24 | 25 | func getStakingPool(log *zap.Logger) stakingPool { 26 | 27 | var sp stakingPool 28 | 29 | res, _ := runRESTCommand("/staking/pool") 30 | json.Unmarshal(res, &sp) 31 | 32 | // log 33 | if strings.Contains(string(res), "not found") { 34 | // handle error 35 | log.Fatal("REST-Server", zap.Bool("Success", false), zap.String("err", string(res),)) 36 | } else { 37 | log.Info("REST-Server", zap.Bool("Success", true), zap.String("err", "nil"), zap.String("Get Data", "Staking Pool"),) 38 | } 39 | 40 | sp.Result.Total_supply = getTotalSupply("atom", log) 41 | 42 | return sp 43 | } 44 | 45 | func getTotalSupply(denom string, log *zap.Logger) float64 { 46 | 47 | var ts totalSupply 48 | 49 | res, _ := runRESTCommand("/supply/total/u" +denom) 50 | json.Unmarshal(res, &ts) 51 | 52 | // log 53 | if strings.Contains(string(res), "not found") { 54 | // handle error 55 | log.Fatal("REST-Server", zap.Bool("Success", false), zap.String("err", string(res),)) 56 | } else { 57 | log.Info("REST-Server", zap.Bool("Success", true), zap.String("err", "nil"), zap.String("Get Data", "Total Supply"),) 58 | } 59 | 60 | return utils.StringToFloat64(ts.Result) 61 | } 62 | -------------------------------------------------------------------------------- /getData/rest/validators.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "strings" 5 | "encoding/json" 6 | "go.uber.org/zap" 7 | ) 8 | 9 | type validators struct { 10 | Height string `json:"height"` 11 | Result validator 12 | } 13 | 14 | type validator struct { 15 | OperAddr string `json:"operator_address"` 16 | ConsPubKey string `json:"consensus_pubkey"` 17 | Jailed bool `json:"jailed"` 18 | Status int `json:"status"` 19 | Tokens string `json:"tokens"` 20 | DelegatorShares string `json:"delegator_shares"` 21 | Description struct { 22 | Moniker string `json:"moniker"` 23 | Identity string `json:"identity"` 24 | Website string `json:"website"` 25 | Details string `json:"details"` 26 | } 27 | UnbondingHeight string `json:"unbonding_height"` 28 | UnbondingTime string `json:"unbonding_time"` 29 | Commission struct { 30 | Commission_rates struct { 31 | Rate string `json:"rate"` 32 | Max_rate string `json:"max_rate"` 33 | Max_change_rate string `json:"max_change_rate"` 34 | } 35 | UpdateTime string `json:"update_time"` 36 | } 37 | MinSelfDelegation string `json:"min_self_delegation"` 38 | } 39 | 40 | func getValidators(log *zap.Logger) validator { 41 | 42 | var v validators 43 | 44 | res, _ := runRESTCommand("/staking/validators/" +OperAddr) 45 | json.Unmarshal(res, &v) 46 | 47 | // log 48 | if strings.Contains(string(res), "not found") { 49 | // handle error 50 | log.Fatal("REST-Server", zap.Bool("Success", false), zap.String("err", string(res),)) 51 | } else { 52 | log.Info("REST-Server", zap.Bool("Success", true), zap.String("err", "nil"), zap.String("Get Data", "Validators"),) 53 | } 54 | 55 | return v.Result 56 | } 57 | -------------------------------------------------------------------------------- /getData/rest/validatorsets.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "fmt" 5 | "encoding/json" 6 | "sort" 7 | "strconv" 8 | "go.uber.org/zap" 9 | "strings" 10 | ) 11 | 12 | type validatorsets struct { 13 | 14 | Height string `json:"height"` 15 | 16 | Result struct { 17 | Block_Height string `json:"block_height"` 18 | Validators []struct { 19 | ConsAddr string `json:"address"` 20 | ConsPubKey string `json:"pub_key"` 21 | ProposerPriority string `json:"proposer_priority"` 22 | VotingPower string `json:"voting_power"` 23 | } 24 | 25 | } 26 | } 27 | 28 | func getValidatorsets(currentBlockHeight int64, log *zap.Logger) map[string][]string { 29 | 30 | var vSets validatorsets 31 | var vSetsResult map[string][]string = make(map[string][]string) 32 | 33 | res, _ := runRESTCommand("/validatorsets/" +fmt.Sprint(currentBlockHeight)) 34 | json.Unmarshal(res, &vSets) 35 | 36 | // log 37 | if strings.Contains(string(res), "not found") { 38 | // handle error 39 | log.Fatal("REST-Server", zap.Bool("Success", false), zap.String("err", string(res),)) 40 | } else { 41 | log.Info("REST-Server", zap.Bool("Success", true), zap.String("err", "nil"), zap.String("Get Data", "Validatorsets"),) 42 | } 43 | 44 | 45 | 46 | for _, value := range vSets.Result.Validators { 47 | // address, voting_power, proposer_priority, proposer_ranking 48 | vSetsResult[value.ConsPubKey] = []string{value.ConsAddr, value.VotingPower, value.ProposerPriority, "0"} 49 | } 50 | 51 | return Sort(vSetsResult) 52 | } 53 | 54 | func Sort(mapValue map[string][]string) map[string][]string { 55 | 56 | keys := []string{} 57 | newMapValue := mapValue 58 | 59 | for key := range mapValue { 60 | keys = append(keys, key) 61 | } 62 | 63 | // Sort by proposer_priority 64 | sort.Slice(keys, func(i, j int) bool { 65 | a, _ := strconv.Atoi(mapValue[keys[i]][2]) 66 | b, _ := strconv.Atoi(mapValue[keys[j]][2]) 67 | return a > b 68 | }) 69 | 70 | for i, key := range keys { 71 | // proposer_ranking 72 | newMapValue[key][3] = strconv.Itoa(i + 1) 73 | } 74 | return newMapValue 75 | } 76 | -------------------------------------------------------------------------------- /getData/rpc/commit.go: -------------------------------------------------------------------------------- 1 | package rpc 2 | 3 | import ( 4 | "fmt" 5 | ctypes "github.com/tendermint/tendermint/rpc/core/types" 6 | ) 7 | 8 | type commitInfo struct { 9 | ChainId string 10 | VoteType float64 // [0]: false, [1]: prevote, [2]: precommit 11 | ValidatorPrecommitStatus float64 // [0]: false, [1]: true 12 | ValidatorProposingStatus float64 // [0]: false, [1]: true 13 | } 14 | 15 | func getCommit(commitData *ctypes.ResultCommit, consHexAddr string) commitInfo { 16 | 17 | var cInfo commitInfo 18 | 19 | blockProposer := fmt.Sprint(commitData.SignedHeader.Header.ProposerAddress) 20 | 21 | cInfo.ChainId = commitData.SignedHeader.Header.ChainID 22 | cInfo.VoteType, cInfo.ValidatorPrecommitStatus, cInfo.ValidatorProposingStatus = 0.0, 0.0, 0.0 23 | 24 | for _, v := range commitData.SignedHeader.Commit.Precommits { 25 | 26 | func() { 27 | defer func() { 28 | 29 | if r := recover(); r != nil { 30 | // precommit failure validator 31 | } 32 | }() 33 | 34 | if consHexAddr == fmt.Sprint(v.ValidatorAddress) { 35 | 36 | cInfo.VoteType = float64(v.Type) 37 | 38 | if v.Type == 2 { 39 | cInfo.ValidatorPrecommitStatus = 1.0 40 | } 41 | } 42 | 43 | if consHexAddr == blockProposer { 44 | cInfo.ValidatorProposingStatus = 1.0 45 | } 46 | }() 47 | 48 | } 49 | 50 | return cInfo 51 | } 52 | -------------------------------------------------------------------------------- /getData/rpc/rpc.go: -------------------------------------------------------------------------------- 1 | package rpc 2 | 3 | import ( 4 | "fmt" 5 | "go.uber.org/zap" 6 | 7 | tmclient "github.com/tendermint/tendermint/rpc/client" 8 | ) 9 | 10 | 11 | type RPCData struct { 12 | Commit commitInfo 13 | } 14 | 15 | var ( 16 | Addr string 17 | 18 | Client *tmclient.HTTP 19 | ) 20 | 21 | func newRPCData() *RPCData { 22 | 23 | rd := &RPCData { 24 | // 25 | } 26 | 27 | return rd 28 | } 29 | 30 | func GetData(blockHeight int64, consHexAddr string, log *zap.Logger) *RPCData { 31 | 32 | rd := newRPCData() 33 | 34 | var commitHeight int64 = blockHeight -1 35 | 36 | commitData, err := Client.Commit(&commitHeight) 37 | // log 38 | if err != nil { 39 | // handle error 40 | log.Fatal("RPC-Server", zap.Bool("Success", false), zap.String("err", fmt.Sprint(err),)) 41 | } else { 42 | log.Info("RPC-Server", zap.Bool("Success", true), zap.String("err", "nil"), zap.String("Get Data", "Commit Data"),) 43 | } 44 | 45 | rd.Commit = getCommit(commitData, consHexAddr) 46 | 47 | 48 | return rd 49 | } 50 | 51 | func OpenSocket(log *zap.Logger) { 52 | 53 | Client = tmclient.NewHTTP("tcp://"+Addr, "/websocket") 54 | 55 | err := Client.Start() 56 | 57 | if err != nil { 58 | // handle error 59 | log.Fatal("RPC-Server", zap.Bool("Success", false), zap.String("err", fmt.Sprintf("%s", err)),) 60 | } else { 61 | log.Info("RPC-Server", zap.Bool("Success", true), zap.String("err", "nil"), zap.String("Open Socket", "tcp://" +Addr +"/websocket"),) 62 | } 63 | 64 | 65 | defer Client.Stop() 66 | 67 | } 68 | 69 | func BlockHeight() (res int64) { 70 | 71 | info, _:= Client.ABCIInfo() 72 | 73 | res = info.Response.LastBlockHeight 74 | 75 | return res 76 | } 77 | 78 | 79 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/node-a-team/cosmos-validator_exporter 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/BurntSushi/toml v0.3.1 7 | github.com/cosmos/cosmos-sdk v0.37.4 8 | github.com/prometheus/client_golang v1.3.0 9 | github.com/tendermint/tendermint v0.32.8 10 | go.uber.org/zap v1.13.0 11 | ) 12 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= 3 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 4 | github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= 5 | github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= 6 | github.com/Workiva/go-datastructures v1.0.50/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= 7 | github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= 8 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 9 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 10 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 11 | github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 12 | github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= 13 | github.com/bartekn/go-bip39 v0.0.0-20171116152956-a05967ea095d/go.mod h1:icNx/6QdFblhsEjZehARqbNumymUT/ydwlLojFdv7Sk= 14 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 15 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 16 | github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 17 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 18 | github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= 19 | github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d h1:xG8Pj6Y6J760xwETNmMzmlt38QSwz0BLp1cZ09g27uw= 20 | github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0= 21 | github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= 22 | github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a h1:RQMUrEILyYJEoAT34XS/kLu40vC0+po/UfxrBBA4qZE= 23 | github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= 24 | github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= 25 | github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= 26 | github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= 27 | github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= 28 | github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= 29 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 30 | github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= 31 | github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= 32 | github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= 33 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 34 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 35 | github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= 36 | github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= 37 | github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= 38 | github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 39 | github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 40 | github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= 41 | github.com/cosmos/cosmos-sdk v0.37.4 h1:1ioXxkpiS+wOgaUbROeDIyuF7hciU5nti0TSyBmV2Ok= 42 | github.com/cosmos/cosmos-sdk v0.37.4/go.mod h1:Axr+Q+G2Ffduxt4zMA6KwxxvyVSKPB9+nXZVPKgpC2c= 43 | github.com/cosmos/go-bip39 v0.0.0-20180618194314-52158e4697b8/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= 44 | github.com/cosmos/ledger-cosmos-go v0.10.3/go.mod h1:J8//BsAGTo3OC/vDLjMRFLW6q0WAaXvHnVc7ZmE8iUY= 45 | github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9QWFanOyI= 46 | github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= 47 | github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 48 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 49 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 50 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 51 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 52 | github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= 53 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 54 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 55 | github.com/etcd-io/bbolt v1.3.2/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= 56 | github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= 57 | github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= 58 | github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= 59 | github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= 60 | github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= 61 | github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= 62 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 63 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 64 | github.com/go-kit/kit v0.6.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 65 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 66 | github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= 67 | github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 68 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 69 | github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA= 70 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 71 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 72 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 73 | github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= 74 | github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 75 | github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= 76 | github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 77 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 78 | github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 79 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 80 | github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= 81 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 82 | github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= 83 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 84 | github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= 85 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 86 | github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= 87 | github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 88 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 89 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 90 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 91 | github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= 92 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 93 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 94 | github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= 95 | github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 96 | github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 97 | github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= 98 | github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 99 | github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= 100 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= 101 | github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= 102 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 103 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 104 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 105 | github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 106 | github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= 107 | github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 108 | github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= 109 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 110 | github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 111 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 112 | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 113 | github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= 114 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 115 | github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= 116 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 117 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 118 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 119 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 120 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 121 | github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= 122 | github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= 123 | github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 124 | github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 125 | github.com/mattn/go-isatty v0.0.6/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 126 | github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= 127 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 128 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 129 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 130 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 131 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 132 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 133 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 134 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 135 | github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= 136 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 137 | github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 138 | github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 139 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 140 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 141 | github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= 142 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 143 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 144 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 145 | github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= 146 | github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= 147 | github.com/prometheus/client_golang v1.3.0 h1:miYCvYqFXtl/J9FIy8eNpBfYthAEFg+Ys0XyUVEcDsc= 148 | github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= 149 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 150 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 151 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 152 | github.com/prometheus/client_model v0.1.0 h1:ElTg5tNp4DqfV7UQjDqv2+RJlNzsDtvNAWccbItceIE= 153 | github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 154 | github.com/prometheus/common v0.0.0-20181020173914-7e9e6cabbd39/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= 155 | github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= 156 | github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 157 | github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 158 | github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY= 159 | github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= 160 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 161 | github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 162 | github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 163 | github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= 164 | github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= 165 | github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= 166 | github.com/rakyll/statik v0.1.5/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6GX8Zs= 167 | github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165 h1:nkcn14uNmFEuGCb2mBZbBb24RdNRL08b/wb+xBOYpuk= 168 | github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= 169 | github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 170 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 171 | github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= 172 | github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= 173 | github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= 174 | github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= 175 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 176 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 177 | github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa/go.mod h1:oJyF+mSPHbB5mVY2iO9KV3pTt/QbIkGaO8gQ2WrDbP4= 178 | github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= 179 | github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 180 | github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= 181 | github.com/spf13/afero v1.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= 182 | github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 183 | github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= 184 | github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= 185 | github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= 186 | github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= 187 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 188 | github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= 189 | github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= 190 | github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= 191 | github.com/spf13/viper v1.5.0/go.mod h1:AkYRkVJF8TkSG/xet6PzXX+l39KhhXa2pdqVSxnTcn4= 192 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 193 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 194 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 195 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 196 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 197 | github.com/stumble/gorocksdb v0.0.3/go.mod h1:v6IHdFBXk5DJ1K4FZ0xi+eY737quiiBxYtSWXadLybY= 198 | github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= 199 | github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965 h1:1oFLiOyVl+W7bnBzGhf7BbIv9loSFQcieWWYIjLqcAw= 200 | github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= 201 | github.com/tendermint/btcd v0.1.1/go.mod h1:DC6/m53jtQzr/NFmMNEu0rxf18/ktVoVtMrnDD5pN+U= 202 | github.com/tendermint/crypto v0.0.0-20180820045704-3764759f34a5/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk= 203 | github.com/tendermint/go-amino v0.14.1/go.mod h1:i/UKE5Uocn+argJJBb12qTZsCDBcAYMbR92AaJVmKso= 204 | github.com/tendermint/go-amino v0.15.0 h1:TC4e66P59W7ML9+bxio17CPKnxW3nKIRAYskntMAoRk= 205 | github.com/tendermint/go-amino v0.15.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= 206 | github.com/tendermint/iavl v0.12.4/go.mod h1:8LHakzt8/0G3/I8FUU0ReNx98S/EP6eyPJkAUvEXT/o= 207 | github.com/tendermint/tendermint v0.32.1/go.mod h1:jmPDAKuNkev9793/ivn/fTBnfpA9mGBww8MPRNPNxnU= 208 | github.com/tendermint/tendermint v0.32.7/go.mod h1:D2+A3pNjY+Po72X0mTfaXorFhiVI8dh/Zg640FGyGtE= 209 | github.com/tendermint/tendermint v0.32.8 h1:eOaLJGRi5x/Rb23fiVsxq9c5fZ/6O5QplExlGjNPDVI= 210 | github.com/tendermint/tendermint v0.32.8/go.mod h1:5/B1XZjNYtVBso8o1l/Eg4A0Mhu42lDcmftoQl95j/E= 211 | github.com/tendermint/tm-db v0.1.1/go.mod h1:0cPKWu2Mou3IlxecH+MEUSYc1Ch537alLe6CpFrKzgw= 212 | github.com/tendermint/tm-db v0.2.0 h1:rJxgdqn6fIiVJZy4zLpY1qVlyD0TU6vhkT4kEf71TQQ= 213 | github.com/tendermint/tm-db v0.2.0/go.mod h1:0cPKWu2Mou3IlxecH+MEUSYc1Ch537alLe6CpFrKzgw= 214 | github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= 215 | github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= 216 | github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= 217 | github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= 218 | github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= 219 | github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= 220 | go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= 221 | go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= 222 | go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 223 | go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= 224 | go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= 225 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 226 | go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc= 227 | go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= 228 | go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= 229 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 230 | go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU= 231 | go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= 232 | golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 233 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 234 | golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 235 | golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 236 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 237 | golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 238 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk= 239 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 240 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 241 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 242 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 243 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 244 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 245 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 246 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 247 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 248 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 249 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 250 | golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 251 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 252 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 253 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 254 | golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 255 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 256 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 257 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7 h1:rTIdg5QFRR7XCaK4LCjBiPbx8j4DQRpdYMnGn/bJUEU= 258 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 259 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 260 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 261 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 262 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 263 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 264 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 265 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 266 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 267 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 268 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 269 | golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 270 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 271 | golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 272 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 273 | golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 274 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 275 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 276 | golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 277 | golang.org/x/sys v0.0.0-20191220142924-d4481acd189f h1:68K/z8GLUxV76xGSqwTWw2gyk/jwn79LUL43rES2g8o= 278 | golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 279 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= 280 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 281 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 282 | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 283 | golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 284 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 285 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 286 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 287 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 288 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 289 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 290 | golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 291 | golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 292 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 293 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 294 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 295 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 296 | google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 297 | google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 298 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= 299 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 300 | google.golang.org/grpc v1.13.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= 301 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 302 | google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 303 | google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 304 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 305 | google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 306 | google.golang.org/grpc v1.25.1 h1:wdKvqQk7IttEw92GoRyKG2IDrUIpgpj6H6m81yfeMW0= 307 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 308 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 309 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 310 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 311 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 312 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 313 | gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= 314 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 315 | gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 316 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 317 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 318 | gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= 319 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 320 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 321 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 322 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 323 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "os" 7 | "go.uber.org/zap" 8 | 9 | sdk "github.com/cosmos/cosmos-sdk/types" 10 | 11 | "github.com/prometheus/client_golang/prometheus/promhttp" 12 | 13 | cfg "github.com/node-a-team/cosmos-validator_exporter/config" 14 | "github.com/node-a-team/cosmos-validator_exporter/exporter" 15 | rpc "github.com/node-a-team/cosmos-validator_exporter/getData/rpc" 16 | ) 17 | 18 | const ( 19 | bech32MainPrefix = "cosmos" 20 | ) 21 | 22 | func main() { 23 | 24 | log,_ := zap.NewDevelopment() 25 | defer log.Sync() 26 | 27 | config := sdk.GetConfig() 28 | config.SetBech32PrefixForAccount(bech32MainPrefix, bech32MainPrefix+sdk.PrefixPublic) 29 | config.SetBech32PrefixForValidator(bech32MainPrefix+sdk.PrefixValidator+sdk.PrefixOperator, bech32MainPrefix+sdk.PrefixValidator+sdk.PrefixOperator+sdk.PrefixPublic) 30 | config.SetBech32PrefixForConsensusNode(bech32MainPrefix+sdk.PrefixValidator+sdk.PrefixConsensus, bech32MainPrefix+sdk.PrefixValidator+sdk.PrefixConsensus+sdk.PrefixPublic) 31 | 32 | cfg.ConfigPath = os.Args[1] 33 | 34 | port := cfg.Init() 35 | rpc.OpenSocket(log) 36 | 37 | http.Handle("/metrics", promhttp.Handler()) 38 | go exporter.Start(log) 39 | 40 | err := http.ListenAndServe(":" +port, nil) 41 | // log 42 | if err != nil { 43 | // handle error 44 | log.Fatal("HTTP Handle", zap.Bool("Success", false), zap.String("err", fmt.Sprint(err),)) 45 | } else { 46 | log.Info("HTTP Handle", zap.Bool("Success", true), zap.String("err", "nil"), zap.String("Listen&Serve", "Prometheus Handler(Port: " +port +")"),) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /utils/address.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | "go.uber.org/zap" 6 | 7 | "github.com/tendermint/tendermint/libs/bech32" 8 | 9 | sdk "github.com/cosmos/cosmos-sdk/types" 10 | 11 | ) 12 | 13 | const ( 14 | bech32MainPrefix = "cosmos" 15 | ) 16 | 17 | var ( 18 | Bech32Prefixes = []string{ 19 | // account's address 20 | bech32MainPrefix, 21 | // account's public key 22 | bech32MainPrefix+sdk.PrefixPublic, 23 | // validator's operator address 24 | bech32MainPrefix+sdk.PrefixValidator+sdk.PrefixOperator, 25 | // validator's operator public key 26 | bech32MainPrefix+sdk.PrefixValidator+sdk.PrefixOperator+sdk.PrefixPublic, 27 | // consensus node address 28 | bech32MainPrefix+sdk.PrefixValidator+sdk.PrefixConsensus, 29 | // consensus node public key 30 | bech32MainPrefix+sdk.PrefixValidator+sdk.PrefixConsensus+sdk.PrefixPublic, 31 | } 32 | ) 33 | 34 | // Bech32 Addr -> Hex Addr 35 | func Bech32AddrToHexAddr(bech32str string, log *zap.Logger) string { 36 | _, bz, err := bech32.DecodeAndConvert(bech32str) 37 | if err != nil { 38 | // handle error 39 | log.Fatal("Utils-Address", zap.Bool("Success", false), zap.String("err", fmt.Sprint(err),)) 40 | } else { 41 | // log.Info("Utils-Address", zap.Bool("Success", true), zap.String("err", "nil"), zap.String("Change Address", "Bech32Addr To HexAddr"),) 42 | } 43 | 44 | return fmt.Sprintf("%X", bz) 45 | } 46 | 47 | func GetAccAddrFromOperAddr(operAddr string, log *zap.Logger) string { 48 | 49 | // Get HexAddress 50 | hexAddr, err := sdk.ValAddressFromBech32(operAddr) 51 | // log 52 | if err != nil { 53 | // handle error 54 | log.Fatal("Utils-Address", zap.Bool("Success", false), zap.String("err", fmt.Sprint(err),)) 55 | } else { 56 | // log.Info("Utils-Address", zap.Bool("Success", true), zap.String("err", "nil"), zap.String("Change Address", "OperAddr To HexAddr"),) 57 | } 58 | 59 | accAddr, err := sdk.AccAddressFromHex(fmt.Sprint(hexAddr)) 60 | // log 61 | if err != nil { 62 | // handle error 63 | log.Fatal("Utils-Address", zap.Bool("Success", false), zap.String("err", fmt.Sprint(err),)) 64 | } else { 65 | // log.Info("Utils-Address", zap.Bool("Success", true), zap.String("err", "nil"), zap.String("Change Address", "HexAddr To AccAddr"),) 66 | } 67 | 68 | return accAddr.String() 69 | } 70 | 71 | -------------------------------------------------------------------------------- /utils/converter.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "strconv" 5 | ) 6 | 7 | func StringToFloat64(str string) float64 { 8 | 9 | var result float64 10 | 11 | result, _ = strconv.ParseFloat(str, 64) 12 | 13 | return result 14 | } 15 | 16 | func BoolToFloat64(b bool) float64 { 17 | 18 | var result float64 19 | 20 | if b == true { 21 | result = 1 22 | } else { 23 | result = 0 24 | } 25 | 26 | return result 27 | } 28 | --------------------------------------------------------------------------------