From dd919a4e9f8f4073a92842d0768c5be0350f5b33 Mon Sep 17 00:00:00 2001 From: Thiago Figueiredo Date: Wed, 2 Jun 2021 16:15:53 -0300 Subject: [PATCH 1/7] [gov] Migrate to new politeia tlog API --- cmd/dcrdata/api/apiroutes.go | 72 +- cmd/dcrdata/config.go | 29 +- cmd/dcrdata/config_test.go | 13 - cmd/dcrdata/explorer/explorer.go | 59 +- cmd/dcrdata/explorer/explorermiddleware.go | 10 +- cmd/dcrdata/explorer/explorerroutes.go | 84 +-- cmd/dcrdata/explorer/explorerroutes_test.go | 24 +- cmd/dcrdata/go.mod | 6 +- cmd/dcrdata/go.sum | 598 ++++++++++++--- cmd/dcrdata/main.go | 126 +--- .../js/controllers/proposal_controller.js | 32 +- cmd/dcrdata/views/proposal.tmpl | 56 +- cmd/dcrdata/views/proposals.tmpl | 23 +- db/dbtypes/types.go | 7 - db/dcrpg/chkdcrpg/main.go | 3 +- db/dcrpg/go.mod | 1 - db/dcrpg/go.sum | 2 - db/dcrpg/indexing.go | 36 - db/dcrpg/internal/indexes.go | 68 +- db/dcrpg/internal/stakestmts.go | 80 +- db/dcrpg/pgblockchain.go | 172 +---- db/dcrpg/pgblockchain_common_test.go | 10 - db/dcrpg/queries.go | 55 -- db/dcrpg/tables.go | 2 - gov/go.mod | 4 +- gov/go.sum | 636 +++++++++++++--- gov/politeia/piclient/piclient.go | 130 ---- gov/politeia/piclient/piclient_test.go | 58 -- gov/politeia/proposals.go | 710 +++++++++++------- gov/politeia/proposals_test.go | 571 -------------- gov/politeia/types/types.go | 336 +++------ gov/politeia/util.go | 118 +++ 32 files changed, 1942 insertions(+), 2189 deletions(-) delete mode 100644 gov/politeia/piclient/piclient.go delete mode 100644 gov/politeia/piclient/piclient_test.go delete mode 100644 gov/politeia/proposals_test.go create mode 100644 gov/politeia/util.go diff --git a/cmd/dcrdata/api/apiroutes.go b/cmd/dcrdata/api/apiroutes.go index c4b583cf2..36f633c44 100644 --- a/cmd/dcrdata/api/apiroutes.go +++ b/cmd/dcrdata/api/apiroutes.go @@ -33,6 +33,7 @@ import ( m "github.com/decred/dcrdata/cmd/dcrdata/middleware" "github.com/decred/dcrdata/exchanges/v3" "github.com/decred/dcrdata/gov/v4/agendas" + "github.com/decred/dcrdata/gov/v4/politeia" apitypes "github.com/decred/dcrdata/v6/api/types" "github.com/decred/dcrdata/v6/db/cache" "github.com/decred/dcrdata/v6/db/dbtypes" @@ -70,7 +71,6 @@ type DataSource interface { Height() int64 AllAgendas() (map[string]dbtypes.MileStone, error) GetTicketInfo(txid string) (*apitypes.TicketInfo, error) - ProposalVotes(proposalToken string) (*dbtypes.ProposalChartsData, error) PowerlessTickets() (*apitypes.PowerlessTickets, error) GetStakeInfoExtendedByHash(hash string) *apitypes.StakeInfoExtended GetStakeInfoExtendedByHeight(idx int) *apitypes.StakeInfoExtended @@ -111,29 +111,29 @@ type DataSource interface { // dcrdata application context used by all route handlers type appContext struct { - nodeClient *rpcclient.Client - Params *chaincfg.Params - DataSource DataSource - Status *apitypes.Status - xcBot *exchanges.ExchangeBot - AgendaDB *agendas.AgendaDB - maxCSVAddrs int - charts *cache.ChartData - isPiDisabled bool // is piparser disabled + nodeClient *rpcclient.Client + Params *chaincfg.Params + DataSource DataSource + Status *apitypes.Status + xcBot *exchanges.ExchangeBot + AgendaDB *agendas.AgendaDB + ProposalsDB *politeia.ProposalsDB + maxCSVAddrs int + charts *cache.ChartData } // AppContextConfig is the configuration for the appContext and the only // argument to its constructor. type AppContextConfig struct { - Client *rpcclient.Client - Params *chaincfg.Params - DataSource DataSource - XcBot *exchanges.ExchangeBot - AgendasDBInstance *agendas.AgendaDB - MaxAddrs int - Charts *cache.ChartData - IsPiparserDisabled bool - AppVer string + Client *rpcclient.Client + Params *chaincfg.Params + DataSource DataSource + XcBot *exchanges.ExchangeBot + AgendasDBInstance *agendas.AgendaDB + ProposalsDB *politeia.ProposalsDB + MaxAddrs int + Charts *cache.ChartData + AppVer string } // NewContext constructs a new appContext from the RPC client and database, and @@ -149,15 +149,15 @@ func NewContext(cfg *AppContextConfig) *appContext { } return &appContext{ - nodeClient: cfg.Client, - Params: cfg.Params, - DataSource: cfg.DataSource, - xcBot: cfg.XcBot, - AgendaDB: cfg.AgendasDBInstance, - Status: apitypes.NewStatus(uint32(nodeHeight), conns, APIVersion, cfg.AppVer, cfg.Params.Name), - maxCSVAddrs: cfg.MaxAddrs, - charts: cfg.Charts, - isPiDisabled: cfg.IsPiparserDisabled, + nodeClient: cfg.Client, + Params: cfg.Params, + DataSource: cfg.DataSource, + xcBot: cfg.XcBot, + AgendaDB: cfg.AgendasDBInstance, + ProposalsDB: cfg.ProposalsDB, + Status: apitypes.NewStatus(uint32(nodeHeight), conns, APIVersion, cfg.AppVer, cfg.Params.Name), + maxCSVAddrs: cfg.MaxAddrs, + charts: cfg.Charts, } } @@ -1200,28 +1200,22 @@ func (c *appContext) getTicketPoolByDate(w http.ResponseWriter, r *http.Request) } func (c *appContext) getProposalChartData(w http.ResponseWriter, r *http.Request) { - if c.isPiDisabled { - errMsg := "piparser is disabled." - apiLog.Errorf("%s. Remove the disable-piparser flag to activate it.", errMsg) - http.Error(w, errMsg, http.StatusServiceUnavailable) - return - } - token := m.GetProposalTokenCtx(r) - votesData, err := c.DataSource.ProposalVotes(token) + + proposal, err := c.ProposalsDB.ProposalByToken(token) if dbtypes.IsTimeoutErr(err) { - apiLog.Errorf("ProposalVotes: %v", err) + apiLog.Errorf("ProposalByToken: %v", err) http.Error(w, "Database timeout.", http.StatusServiceUnavailable) return } if err != nil { - apiLog.Errorf("Unable to get proposals votes for token %s : %v", token, err) + apiLog.Errorf("Unable to get proposal chart data for token %s : %v", token, err) http.Error(w, http.StatusText(http.StatusUnprocessableEntity), http.StatusUnprocessableEntity) return } - writeJSON(w, votesData, m.GetIndentCtx(r)) + writeJSON(w, proposal.ChartData, m.GetIndentCtx(r)) } func (c *appContext) getBlockSize(w http.ResponseWriter, r *http.Request) { diff --git a/cmd/dcrdata/config.go b/cmd/dcrdata/config.go index 2126d1432..6409de53a 100644 --- a/cmd/dcrdata/config.go +++ b/cmd/dcrdata/config.go @@ -66,7 +66,7 @@ var ( defaultAgendasDBFileName = "agendas.db" defaultProposalsFileName = "proposals.db" - defaultPoliteiaAPIURl = "https://proposals.decred.org" + defaultPoliteiaURL = "https://proposals.decred.org/" defaultChartsCacheDump = "chartscache.gob" defaultPGHost = "127.0.0.1:5432" @@ -124,13 +124,10 @@ type config struct { MempoolMaxInterval int `long:"mp-max-interval" description:"The maximum time in seconds between mempool reports (within a couple seconds), regardless of number of new tickets seen." env:"DCRDATA_MEMPOOL_MAX_INTERVAL"` MPTriggerTickets int `long:"mp-ticket-trigger" description:"The minimum number of new tickets that must be seen to trigger a new mempool report." env:"DCRDATA_MP_TRIGGER_TICKETS"` - // Politeia/proposals and consensus agendas + // Consensus agendas and politeia proposals AgendasDBFileName string `long:"agendadbfile" description:"Agendas DB file name (default is agendas.db)." env:"DCRDATA_AGENDAS_DB_FILE_NAME"` ProposalsFileName string `long:"proposalsdbfile" description:"Proposals DB file name (default is proposals.db)." env:"DCRDATA_PROPOSALS_DB_FILE_NAME"` - PoliteiaAPIURL string `long:"politeiaurl" description:"Defines the root API politeia URL (defaults to https://proposals.decred.org)." env:"DCRDATA_POLITEIA_URL"` - PiPropRepoOwner string `long:"piproposalsowner" description:"Defines the owner to the github repo where Politeia's proposals are pushed." env:"DCRDATA_PI_REPO_OWNER"` - PiPropRepoName string `long:"piproposalsrepo" description:"Defines the name of the github repo where Politeia's proposals are pushed." env:"DCRDATA_PROPS_REPO"` - DisablePiParser bool `long:"disable-piparser" description:"Disables the piparser tool from running." env:"DCRDATA_DISABLE_PIPARSER"` + PoliteiaURL string `long:"politeiaurl" description:"Defines the root API politeia URL (defaults to https://proposals.decred.org/)." env:"DCRDATA_POLITEIA_URL"` // Caching and optimization. AddrCacheCap int `long:"addr-cache-cap" description:"Address cache capacity in bytes." env:"DCRDATA_ADDR_CACHE_CAP"` @@ -182,7 +179,7 @@ var ( ConfigFile: defaultConfigFile, AgendasDBFileName: defaultAgendasDBFileName, ProposalsFileName: defaultProposalsFileName, - PoliteiaAPIURL: defaultPoliteiaAPIURl, + PoliteiaURL: defaultPoliteiaURL, ChartsCacheDump: defaultChartsCacheDump, DebugLevel: defaultLogLevel, HTTPProfPath: defaultHTTPProfPath, @@ -526,8 +523,6 @@ func loadConfig() (*config, error) { activeNet = &netparams.SimNetParams activeChain = chaincfg.SimNetParams() defaultPort = defaultSimnetPort - // If on simnet, disable piparser tool automatically. - cfg.DisablePiParser = true numNets++ } if numNets > 1 { @@ -636,14 +631,6 @@ func loadConfig() (*config, error) { return loadConfigError(err) } - // Checks if the expected format of the API URL was set. It also drops any - // unnecessary parts of the URL. - urlPath, err := retrieveRootPath(cfg.PoliteiaAPIURL) - if err != nil { - return loadConfigError(err) - } - cfg.PoliteiaAPIURL = urlPath - // Check the supplied APIListen address if cfg.APIListen == "" { cfg.APIListen = defaultHost + ":" + defaultPort @@ -654,6 +641,14 @@ func loadConfig() (*config, error) { } } + // Checks if the expected format of the politeia URL was set. It also drops any + // unnecessary parts of the URL. + urlPath, err := retrieveRootPath(cfg.PoliteiaURL) + if err != nil { + return loadConfigError(err) + } + cfg.PoliteiaURL = urlPath + switch cfg.ServerHeader { case "off": cfg.ServerHeader = "" diff --git a/cmd/dcrdata/config_test.go b/cmd/dcrdata/config_test.go index ab28c2e63..f11b18f22 100644 --- a/cmd/dcrdata/config_test.go +++ b/cmd/dcrdata/config_test.go @@ -235,19 +235,6 @@ func TestDefaultConfigTestNetWithEnvAndBadValue(t *testing.T) { } } -func TestDisablePiparserValueOnSimnet(t *testing.T) { - os.Args = append(os.Args, "--simnet") - - cfg, err := loadConfig() - if err != nil { - t.Errorf("expected to find no error but found: %v", err) - } - - if !cfg.DisablePiParser { - t.Fatal("expected DisablePiParser value to be activated but it wasn't") - } -} - func TestRetrieveRootPath(t *testing.T) { type testData struct { RawURL string diff --git a/cmd/dcrdata/explorer/explorer.go b/cmd/dcrdata/explorer/explorer.go index bad6a840d..d02f486db 100644 --- a/cmd/dcrdata/explorer/explorer.go +++ b/cmd/dcrdata/explorer/explorer.go @@ -95,7 +95,6 @@ type explorerDataSource interface { TimeBasedIntervals(timeGrouping dbtypes.TimeBasedGrouping, limit, offset uint64) ([]*dbtypes.BlocksGroupedInfo, error) AgendasVotesSummary(agendaID string) (summary *dbtypes.AgendaSummary, err error) BlockTimeByHeight(height int64) (int64, error) - LastPiParserSync() time.Time GetChainParams() *chaincfg.Params GetExplorerBlock(hash string) *types.BlockInfo GetExplorerBlocks(start int, end int) []*types.BlockBasic @@ -114,13 +113,11 @@ type explorerDataSource interface { Difficulty(timestamp int64) float64 } -// PoliteiaBackend implements methods that manage proposals db data. type PoliteiaBackend interface { - LastProposalsSync() int64 - CheckProposalsUpdates() error - AllProposals(offset, rowsCount int, filterByVoteStatus ...int) (proposals []*pitypes.ProposalInfo, totalCount int, err error) - ProposalByToken(proposalToken string) (*pitypes.ProposalInfo, error) - ProposalByRefID(RefID string) (*pitypes.ProposalInfo, error) + ProposalsLastSync() int64 + ProposalsSync() error + ProposalsAll(offset, rowsCount int, filterByVoteStatus ...int) ([]*pitypes.ProposalRecord, int, error) + ProposalByToken(token string) (*pitypes.ProposalRecord, error) } // agendaBackend implements methods that manage agendas db data. @@ -208,7 +205,7 @@ type explorerUI struct { chartSource ChartDataSource agendasSource agendaBackend voteTracker *agendas.VoteTracker - proposalsSource PoliteiaBackend + proposals PoliteiaBackend dbsSyncing atomic.Value devPrefetch bool templates templates @@ -223,7 +220,7 @@ type explorerUI struct { // displaySyncStatusPage indicates if the sync status page is the only web // page that should be accessible during DB synchronization. displaySyncStatusPage atomic.Value - politeiaAPIURL string + politeiaURL string invsMtx sync.RWMutex invs *types.MempoolInfo @@ -278,21 +275,21 @@ func (exp *explorerUI) StopWebsocketHub() { // ExplorerConfig is the configuration settings for explorerUI. type ExplorerConfig struct { - DataSource explorerDataSource - ChartSource ChartDataSource - UseRealIP bool - AppVersion string - DevPrefetch bool - Viewsfolder string - XcBot *exchanges.ExchangeBot - AgendasSource agendaBackend - Tracker *agendas.VoteTracker - ProposalsSource PoliteiaBackend - PoliteiaURL string - MainnetLink string - TestnetLink string - OnionAddress string - ReloadHTML bool + DataSource explorerDataSource + ChartSource ChartDataSource + UseRealIP bool + AppVersion string + DevPrefetch bool + Viewsfolder string + XcBot *exchanges.ExchangeBot + AgendasSource agendaBackend + Tracker *agendas.VoteTracker + Proposals PoliteiaBackend + PoliteiaURL string + MainnetLink string + TestnetLink string + OnionAddress string + ReloadHTML bool } // New returns an initialized instance of explorerUI @@ -309,8 +306,8 @@ func New(cfg *ExplorerConfig) *explorerUI { exp.xcDone = make(chan struct{}) exp.agendasSource = cfg.AgendasSource exp.voteTracker = cfg.Tracker - exp.proposalsSource = cfg.ProposalsSource - exp.politeiaAPIURL = cfg.PoliteiaURL + exp.proposals = cfg.Proposals + exp.politeiaURL = cfg.PoliteiaURL explorerLinks.Mainnet = cfg.MainnetLink explorerLinks.Testnet = cfg.TestnetLink explorerLinks.MainnetSearch = cfg.MainnetLink + "search?search=" @@ -589,17 +586,15 @@ func (exp *explorerUI) Store(blockData *blockdata.BlockData, msgBlock *wire.MsgB go exp.voteTracker.Refresh() } - // Politeia updates happen hourly. Thus, if blocks take 5 minutes on average - // to mine, then 12 blocks take approximately 1hr. - // https://docs.decred.org/advanced/navigating-politeia-data/#voting-and-comment-data - if newBlockData.Height%12 == 0 && exp.proposalsSource != nil { + // Update proposals data every 5 blocks + if (newBlockData.Height%5 == 0) && exp.proposals != nil { // Update the proposal DB. This is run asynchronously since it involves // a query to Politeia (a remote system) and we do not want to block // execution. go func() { - err := exp.proposalsSource.CheckProposalsUpdates() + err := exp.proposals.ProposalsSync() if err != nil { - log.Errorf("(PoliteiaBackend).CheckProposalsUpdates: %v", err) + log.Errorf("(PoliteiaBackend).ProposalsSync: %v", err) } }() } diff --git a/cmd/dcrdata/explorer/explorermiddleware.go b/cmd/dcrdata/explorer/explorermiddleware.go index 68a86524a..8593deb70 100644 --- a/cmd/dcrdata/explorer/explorermiddleware.go +++ b/cmd/dcrdata/explorer/explorermiddleware.go @@ -27,7 +27,7 @@ const ( ctxTxInOutId ctxAddress ctxAgendaId - ctxProposalRefID + ctxProposalToken ) const ( @@ -144,7 +144,7 @@ func getAgendaIDCtx(r *http.Request) string { } func getProposalTokenCtx(r *http.Request) string { - hash, ok := r.Context().Value(ctxProposalRefID).(string) + hash, ok := r.Context().Value(ctxProposalToken).(string) if !ok { log.Trace("Proposal ref ID not set") return "" @@ -190,11 +190,11 @@ func AgendaPathCtx(next http.Handler) http.Handler { }) } -// ProposalPathCtx embeds "proposalrefID" into the request context +// ProposalPathCtx embeds "proposaltoken" into the request context func ProposalPathCtx(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - proposalRefID := chi.URLParam(r, "proposalrefid") - ctx := context.WithValue(r.Context(), ctxProposalRefID, proposalRefID) + proposalToken := chi.URLParam(r, "proposaltoken") + ctx := context.WithValue(r.Context(), ctxProposalToken, proposalToken) next.ServeHTTP(w, r.WithContext(ctx)) }) } diff --git a/cmd/dcrdata/explorer/explorerroutes.go b/cmd/dcrdata/explorer/explorerroutes.go index d0ce0309c..0c10949da 100644 --- a/cmd/dcrdata/explorer/explorerroutes.go +++ b/cmd/dcrdata/explorer/explorerroutes.go @@ -32,6 +32,7 @@ import ( "github.com/decred/dcrdata/v6/db/dbtypes" "github.com/decred/dcrdata/v6/explorer/types" "github.com/decred/dcrdata/v6/txhelpers" + ticketvotev1 "github.com/decred/politeia/politeiawww/api/ticketvote/v1" humanize "github.com/dustin/go-humanize" ) @@ -1930,6 +1931,7 @@ func (exp *explorerUI) Search(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/address/"+searchStr, http.StatusPermanentRedirect) return } + /* switch _, _, addrErr := txhelpers.AddressValidation(searchStr, exp.ChainParams); addrErr { case txhelpers.AddressErrorNoError, txhelpers.AddressErrorZeroAddress: // valid @@ -1967,13 +1969,9 @@ func (exp *explorerUI) Search(w http.ResponseWriter, r *http.Request) { tryProp := func() bool { // Try proposal token. - proposalInfo, err := exp.proposalsSource.ProposalByToken(searchStr) - if err != nil || proposalInfo.RefID == "" { - // Try proposal RefID. - proposalInfo, err = exp.proposalsSource.ProposalByRefID(searchStr) - } - if err == nil && proposalInfo.RefID != "" { - http.Redirect(w, r, "/proposal/"+proposalInfo.RefID, http.StatusPermanentRedirect) + proposalInfo, err := exp.proposals.ProposalByToken(searchStr) + if err == nil { + http.Redirect(w, r, "/proposal/"+proposalInfo.Token, http.StatusPermanentRedirect) return true } return false @@ -2263,28 +2261,19 @@ func (exp *explorerUI) AgendasPage(w http.ResponseWriter, r *http.Request) { // ProposalPage is the page handler for the "/proposal" path. func (exp *explorerUI) ProposalPage(w http.ResponseWriter, r *http.Request) { - if exp.proposalsSource == nil { - errMsg := "Remove the disable-piparser flag to activate it." - log.Errorf("proposal page is disabled. %s", errMsg) - exp.StatusPage(w, errMsg, fmt.Sprintf(pageDisabledCode, "/proposals"), "", ExpStatusPageDisabled) + if exp.proposals == nil { + log.Errorf("Proposal DB instance is not available") + exp.StatusPage(w, defaultErrorCode, "the proposals DB was not instantiated correctly", + "", ExpStatusNotFound) return } - // Attempts to retrieve a proposal refID from the URL path. - param := getProposalTokenCtx(r) - proposalInfo, err := exp.proposalsSource.ProposalByRefID(param) - if err != nil { - // Check if the URL parameter passed is a proposal token and attempt to - // fetch its data. - proposalInfo, newErr := exp.proposalsSource.ProposalByToken(param) - if newErr == nil && proposalInfo != nil && proposalInfo.RefID != "" { - // redirect to a human readable url (replace the token with the RefID) - http.Redirect(w, r, "/proposal/"+proposalInfo.RefID, http.StatusPermanentRedirect) - return - } + token := getProposalTokenCtx(r) + prop, err := exp.proposals.ProposalByToken(token) + if err != nil { log.Errorf("Template execute failure: %v", err) - exp.StatusPage(w, defaultErrorCode, "the proposal token or RefID does not exist", + exp.StatusPage(w, defaultErrorCode, "the proposal token does not exist", "", ExpStatusNotFound) return } @@ -2292,14 +2281,16 @@ func (exp *explorerUI) ProposalPage(w http.ResponseWriter, r *http.Request) { commonData := exp.commonData(r) str, err := exp.templates.exec("proposal", struct { *CommonPageData - Data *pitypes.ProposalInfo + Data *pitypes.ProposalRecord PoliteiaURL string + ShortToken string Metadata *pitypes.ProposalMetadata }{ CommonPageData: commonData, - Data: proposalInfo, - PoliteiaURL: exp.politeiaAPIURL, - Metadata: proposalInfo.Metadata(int64(commonData.Tip.Height), int64(exp.ChainParams.TargetTimePerBlock/time.Second)), + Data: prop, + PoliteiaURL: exp.politeiaURL, + ShortToken: prop.Token[0:7], + Metadata: prop.Metadata(int64(commonData.Tip.Height), int64(exp.ChainParams.TargetTimePerBlock/time.Second)), }) if err != nil { @@ -2315,9 +2306,9 @@ func (exp *explorerUI) ProposalPage(w http.ResponseWriter, r *http.Request) { // ProposalsPage is the page handler for the "/proposals" path. func (exp *explorerUI) ProposalsPage(w http.ResponseWriter, r *http.Request) { - if exp.proposalsSource == nil { - errMsg := "Remove the disable-piparser flag to activate it." - log.Errorf("proposals page is disabled. %s", errMsg) + if exp.proposals == nil { + errMsg := "Proposal DB instance is not available" + log.Errorf("proposals page error: %s", errMsg) exp.StatusPage(w, errMsg, fmt.Sprintf(pageDisabledCode, "/proposals"), "", ExpStatusPageDisabled) return } @@ -2354,14 +2345,14 @@ func (exp *explorerUI) ProposalsPage(w http.ResponseWriter, r *http.Request) { var err error var count int - var proposals []*pitypes.ProposalInfo + var proposals []*pitypes.ProposalRecord // Check if filter by votes status query parameter was passed. if filterBy > 0 { - proposals, count, err = exp.proposalsSource.AllProposals(int(offset), + proposals, count, err = exp.proposals.ProposalsAll(int(offset), int(rowsCount), int(filterBy)) } else { - proposals, count, err = exp.proposalsSource.AllProposals(int(offset), + proposals, count, err = exp.proposals.ProposalsAll(int(offset), int(rowsCount)) } @@ -2380,31 +2371,40 @@ func (exp *explorerUI) ProposalsPage(w http.ResponseWriter, r *http.Request) { lastOffset = uint64(count) - lastOffsetRows } + // Parse vote statuses map with only used status by the UI. Also + // capitalizes first letter of the string status format. + votesStatus := map[ticketvotev1.VoteStatusT]string{ + ticketvotev1.VoteStatusUnauthorized: "Unauthorized", + ticketvotev1.VoteStatusAuthorized: "Authorized", + ticketvotev1.VoteStatusStarted: "Started", + ticketvotev1.VoteStatusFinished: "Finished", + ticketvotev1.VoteStatusApproved: "Approved", + ticketvotev1.VoteStatusRejected: "Rejected", + ticketvotev1.VoteStatusIneligible: "Ineligible", + } + str, err := exp.templates.exec("proposals", struct { *CommonPageData - Proposals []*pitypes.ProposalInfo - VotesStatus map[pitypes.VoteStatusType]string + Proposals []*pitypes.ProposalRecord + VotesStatus map[ticketvotev1.VoteStatusT]string VStatusFilter int Offset int64 Limit int64 TotalCount int64 LastOffset int64 PoliteiaURL string - LastVotesSync int64 LastPropSync int64 TimePerBlock int64 }{ CommonPageData: exp.commonData(r), Proposals: proposals, - VotesStatus: pitypes.VotesStatuses(), + VotesStatus: votesStatus, Offset: int64(offset), Limit: int64(rowsCount), VStatusFilter: int(filterBy), TotalCount: int64(count), - LastOffset: int64(lastOffset), - PoliteiaURL: exp.politeiaAPIURL, - LastVotesSync: exp.dataSource.LastPiParserSync().UTC().Unix(), - LastPropSync: exp.proposalsSource.LastProposalsSync(), + PoliteiaURL: exp.politeiaURL, + LastPropSync: exp.proposals.ProposalsLastSync(), TimePerBlock: int64(exp.ChainParams.TargetTimePerBlock.Seconds()), }) diff --git a/cmd/dcrdata/explorer/explorerroutes_test.go b/cmd/dcrdata/explorer/explorerroutes_test.go index c88653f42..80cd481d9 100644 --- a/cmd/dcrdata/explorer/explorerroutes_test.go +++ b/cmd/dcrdata/explorer/explorerroutes_test.go @@ -57,18 +57,18 @@ func TestStatusPageResponseCodes(t *testing.T) { var chainDBStub ChainDBStub exp := New(&ExplorerConfig{ - DataSource: &chainDBStub, - UseRealIP: false, - AppVersion: "test", - DevPrefetch: false, - Viewsfolder: viewsPath, - XcBot: nil, - Tracker: nil, - AgendasSource: nil, - ProposalsSource: nil, - PoliteiaURL: "", - MainnetLink: "/", - TestnetLink: "/", + DataSource: &chainDBStub, + UseRealIP: false, + AppVersion: "test", + DevPrefetch: false, + Viewsfolder: viewsPath, + XcBot: nil, + Tracker: nil, + AgendasSource: nil, + Proposals: nil, + PoliteiaURL: "", + MainnetLink: "/", + TestnetLink: "/", }) // handler := http.HandlerFunc() diff --git a/cmd/dcrdata/go.mod b/cmd/dcrdata/go.mod index 872f0d0b3..74e78edea 100644 --- a/cmd/dcrdata/go.mod +++ b/cmd/dcrdata/go.mod @@ -13,9 +13,9 @@ require ( github.com/caarlos0/env/v6 v6.5.0 github.com/decred/dcrd/blockchain/stake/v3 v3.0.0 github.com/decred/dcrd/blockchain/standalone/v2 v2.0.0 - github.com/decred/dcrd/chaincfg/chainhash v1.0.2 + github.com/decred/dcrd/chaincfg/chainhash v1.0.3-0.20200921185235-6d75c7ec1199 github.com/decred/dcrd/chaincfg/v3 v3.0.0 - github.com/decred/dcrd/dcrec v1.0.0 + github.com/decred/dcrd/dcrec v1.0.1-0.20200921185235-6d75c7ec1199 github.com/decred/dcrd/dcrutil/v3 v3.0.0 github.com/decred/dcrd/rpc/jsonrpc/types/v2 v2.3.0 github.com/decred/dcrd/rpcclient/v6 v6.0.2 @@ -25,9 +25,9 @@ require ( github.com/decred/dcrdata/exchanges/v3 v3.0.0 github.com/decred/dcrdata/gov/v4 v4.0.0 github.com/decred/dcrdata/v6 v6.0.0 + github.com/decred/politeia v1.0.1 github.com/decred/slog v1.1.0 github.com/didip/tollbooth/v6 v6.1.0 - github.com/dmigwi/go-piparser/proposals v0.0.0-20191219171828-ae8cbf4067e1 github.com/dustin/go-humanize v1.0.0 github.com/go-chi/chi/v5 v5.0.1 github.com/go-chi/docgen v1.2.0 diff --git a/cmd/dcrdata/go.sum b/cmd/dcrdata/go.sum index 67d389786..93fe8c192 100644 --- a/cmd/dcrdata/go.sum +++ b/cmd/dcrdata/go.sum @@ -1,19 +1,56 @@ +bitbucket.org/creachadair/shell v0.0.6/go.mod h1:8Qqi/cYk7vPnsOePHroKXDJYmb5x7ENhtiFtfZq8K+M= bou.ke/monkey v1.0.1/go.mod h1:FgHuK96Rv2Nlf+0u1OOVDpCMdsWyOFmeeketDHE7LIg= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.60.0/go.mod h1:yw2G51M9IfRboUH61Us8GqCeF1PzPblB823Mn2q2eAU= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/spanner v1.7.0/go.mod h1:sd3K2gZ9Fd0vMPLXzeCrF6fq4i63Q7aTLW/lBIfBkIk= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= decred.org/cspp v0.3.0/go.mod h1:UygjYilC94dER3BEU65Zzyoqy9ngJfWCD2rdJqvUs2A= decred.org/dcrdex v0.0.0-20210401142326-529cb0d17154 h1:mJ9duXGQ1IA1jtZnezrRS4ZJUjSj363m5eB+wSRF/qM= decred.org/dcrdex v0.0.0-20210401142326-529cb0d17154/go.mod h1:7dhGujv+4YSK2ULxUKXhYskj3HsDJC8B1AIlfQrqR7Q= decred.org/dcrwallet v1.6.3-0.20210324151833-873c564976fd/go.mod h1:hNOGyvH53gWdgFB601/ubGRzCPfPtWnEVAi9Grs90y4= decred.org/dcrwallet v1.7.0 h1:U/ew00YBdUlx3rJAynt2OdKDgGzBKK4O89FijBq8iVg= decred.org/dcrwallet v1.7.0/go.mod h1:hNOGyvH53gWdgFB601/ubGRzCPfPtWnEVAi9Grs90y4= -github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM= github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/sprig v2.15.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= +github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OpenBazaar/jsonpb v0.0.0-20171123000858-37d32ddf4eef/go.mod h1:55mCznBcN9WQgrtgaAkv+p2LxeW/tQRdidyyE9D0I5k= @@ -22,21 +59,38 @@ github.com/Sereal/Sereal v0.0.0-20190618215532-0b8ac451a863/go.mod h1:D0JMgToj/W github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/aead/siphash v0.0.0-20170329201724-e404fcfc8885/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ= +github.com/apache/beam v2.27.0+incompatible/go.mod h1:/8NX3Qi8vGstDLLaeaU7+lzVEu/ACaQhYjeefzQ0y1o= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/asdine/storm/v3 v3.0.0-20191014164809-c6fa66c747fe/go.mod h1:wncSIXIbR3lvJQhBpnwAeNPQneL5Vx2KUox2jARUdmw= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/asdine/storm/v3 v3.2.1 h1:I5AqhkPK6nBZ/qJXySdI7ot5BlXSZ7qvDY1zAn5ZJac= github.com/asdine/storm/v3 v3.2.1/go.mod h1:LEpXwGt4pIqrE/XcTvCnZHT5MgZCV6Ub9q7yQzOFWr0= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.20.1-beta.0.20200615134404-e4f59022a387 h1:iVL7ov1l3x6J1WZTqQQJssmO3g3Er6AxnM5c+RIpvo8= github.com/btcsuite/btcd v0.20.1-beta.0.20200615134404-e4f59022a387/go.mod h1:Yktc19YNjh/Iz2//CX0vfRTS4IJKM/RKO5YZ9Fn+Pgo= @@ -60,24 +114,37 @@ github.com/carterjones/go-cloudflare-scraper v0.1.2 h1:GNmlJEfhIVPVXaEItnPSDtwOp github.com/carterjones/go-cloudflare-scraper v0.1.2/go.mod h1:maO/ygX7QWbdh/TzHqr5uR42b2BW81g/05QRx7fpw38= github.com/carterjones/signalr v0.3.5 h1:kJSw+6a9XmsOb/+9HWTnY8SjTrVOdpzCSPV/9IVS2nI= github.com/carterjones/signalr v0.3.5/go.mod h1:SOGIwr/0/4GGNjHWSSginY66OVSaOeM85yWCNytdEwE= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chappjc/trylock v1.0.0 h1:WR9J1cP/+h0x9RoKsxf4I0AnYg7aONYjiwYwys8nibA= github.com/chappjc/trylock v1.0.0/go.mod h1:+FnHf7ZLQpdbR3H9QZUrMKF1jfyHmtpbZddoYhSTzvw= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.15+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/dajohi/goemail v1.0.0/go.mod h1:YyX3pgj9VJX6VQYu8Cbs0GYHzgFUs8q0vX5pLmFvops= +github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -95,37 +162,34 @@ github.com/decred/dcrd/addrmgr v1.0.2/go.mod h1:gNnmTuf/Xkg8ZX3j5GXbajzPrSdf5bA7 github.com/decred/dcrd/addrmgr v1.2.0/go.mod h1:QlZF9vkzwYh0qs25C76SAFZBRscjETga/K28GEE6qIc= github.com/decred/dcrd/blockchain v1.0.0/go.mod h1:nNMgOz12wlasmEJDCuSuMWYSnjDdmB4l38GKuQ/Yd+8= github.com/decred/dcrd/blockchain v1.0.1/go.mod h1:R/4XnwNOTj5IP8jQIUzrJ8zhr/7EOk09IMODwBamZoI= +github.com/decred/dcrd/blockchain v1.0.2 h1:+gJFfgv5LK+LcadyoiMln838/aU3rxDd0Smqogd6fkA= github.com/decred/dcrd/blockchain v1.0.2/go.mod h1:R/4XnwNOTj5IP8jQIUzrJ8zhr/7EOk09IMODwBamZoI= -github.com/decred/dcrd/blockchain v1.1.1 h1:CWr90sZ2YLQz84EGT+X/pzU+9AZB1eXQUy+4fsJSt5w= -github.com/decred/dcrd/blockchain v1.1.1/go.mod h1:zxi/41LgzHitpz/CZu0gxHyFHz8+ysd3lH8E3P5Uifg= github.com/decred/dcrd/blockchain/stake v1.0.0/go.mod h1:opuzF8UouYyQyRJVF00Rdd7OgWb1WKyy1pyU0QYaxz0= github.com/decred/dcrd/blockchain/stake v1.0.1/go.mod h1:hgoGmWMIu2LLApBbcguVpzCEEfX7M2YhuMrQdpohJzc= +github.com/decred/dcrd/blockchain/stake v1.0.2 h1:trUDgZsT5DYiwKu255k4hFtGiVEOAM9IDmP2GqOLYGU= github.com/decred/dcrd/blockchain/stake v1.0.2/go.mod h1:hgoGmWMIu2LLApBbcguVpzCEEfX7M2YhuMrQdpohJzc= -github.com/decred/dcrd/blockchain/stake v1.1.0 h1:kCxZdQ2/UfcD+XjE3wlCv0vLKWR9ZFtjbbTTpudb74o= -github.com/decred/dcrd/blockchain/stake v1.1.0/go.mod h1:WRuaml4bcyZYza1NT3qizlLcQwMIcAQRENvZVb2t884= github.com/decred/dcrd/blockchain/stake/v2 v2.0.0/go.mod h1:jv/rKMcZ87lhvVkHot/tElxeAYEUJ3mnKPHJ7WPq86U= github.com/decred/dcrd/blockchain/stake/v2 v2.0.1/go.mod h1:jv/rKMcZ87lhvVkHot/tElxeAYEUJ3mnKPHJ7WPq86U= +github.com/decred/dcrd/blockchain/stake/v2 v2.0.2/go.mod h1:o2TT/l/YFdrt15waUdlZ3g90zfSwlA0WgQqHV9UGJF4= github.com/decred/dcrd/blockchain/stake/v3 v3.0.0 h1:vr0o0ICjuEzg1End6YtBfwgDuPkg+FYIwGVEz18kFg0= github.com/decred/dcrd/blockchain/stake/v3 v3.0.0/go.mod h1:5GIUwsrHQCJauacgCegIR6t92SaeVi28Qls/BLN9vOw= -github.com/decred/dcrd/blockchain/standalone v1.0.0 h1:bPkFgSV7/NeZI+ZEGhaOP+XccCUBTIJb3YTf8dMwe8g= github.com/decred/dcrd/blockchain/standalone v1.0.0/go.mod h1:U5lOleFSi1nL7heSdLgEtuvg0udS1p3cvHxvLJbihfE= +github.com/decred/dcrd/blockchain/standalone v1.1.0 h1:yclvVGEY09Gf8A4GSAo+NCtL1dW2TYJ4OKp4+g0ICI0= +github.com/decred/dcrd/blockchain/standalone v1.1.0/go.mod h1:6K8ZgzlWM1Kz2TwXbrtiAvfvIwfAmlzrtpA7CVPCUPE= github.com/decred/dcrd/blockchain/standalone/v2 v2.0.0 h1:9gUuH0u/IZNPWBK9K3CxgAWPG7nTqVSsZefpGY4Okns= github.com/decred/dcrd/blockchain/standalone/v2 v2.0.0/go.mod h1:t2qaZ3hNnxHZ5kzVJDgW5sp47/8T5hYJt7SR+/JtRhI= github.com/decred/dcrd/blockchain/v3 v3.0.2/go.mod h1:LD5VA95qdb+DlRiPI8VLBimDqvlDCAJsidZ5oD6nc/U= github.com/decred/dcrd/certgen v1.0.1/go.mod h1:NxEyGwzPHak+h3tNLYAXU4vWuL98HrY9Z59hc1E3SGI= -github.com/decred/dcrd/certgen v1.0.2/go.mod h1:NxEyGwzPHak+h3tNLYAXU4vWuL98HrY9Z59hc1E3SGI= github.com/decred/dcrd/certgen v1.1.0/go.mod h1:ivkPLChfjdAgFh7ZQOtl6kJRqVkfrCq67dlq3AbZBQE= github.com/decred/dcrd/certgen v1.1.1 h1:MYPG5jCysnbF4OiJ1++YumFEu2p/MsM/zxmmqC9mVFg= github.com/decred/dcrd/certgen v1.1.1/go.mod h1:ivkPLChfjdAgFh7ZQOtl6kJRqVkfrCq67dlq3AbZBQE= github.com/decred/dcrd/chaincfg v1.0.1/go.mod h1:O+443mQNPjci+WqWkKta3v2MgJn2u20YWy5mW3c2T7M= +github.com/decred/dcrd/chaincfg v1.1.1 h1:qRZkiA7ucsfsQPE/G/U1OnEUFozDl1MvM4ysJCUndLU= github.com/decred/dcrd/chaincfg v1.1.1/go.mod h1:UlGtnp8Xx9YK+etBTybGjoFGoGXSw2bxZQuAnwfKv6I= -github.com/decred/dcrd/chaincfg v1.2.0/go.mod h1:kpoGTMIriKn5hHRSu5b65+Q9LlGUdbQcMzGujac1BVs= -github.com/decred/dcrd/chaincfg v1.3.0/go.mod h1:kpoGTMIriKn5hHRSu5b65+Q9LlGUdbQcMzGujac1BVs= -github.com/decred/dcrd/chaincfg v1.5.1 h1:u1Xbq0VTnAXIHW5ECqrWe0VYSgf5vWHqpSiwoLBzxAQ= -github.com/decred/dcrd/chaincfg v1.5.1/go.mod h1:FukMzTjkwzjPU+hK7CqDMQe3NMbSZAYU5PAcsx1wlv0= github.com/decred/dcrd/chaincfg/chainhash v1.0.1/go.mod h1:OVfvaOsNLS/A1y4Eod0Ip/Lf8qga7VXCQjUQLbkY0Go= -github.com/decred/dcrd/chaincfg/chainhash v1.0.2 h1:rt5Vlq/jM3ZawwiacWjPa+smINyLRN07EO0cNBV6DGU= github.com/decred/dcrd/chaincfg/chainhash v1.0.2/go.mod h1:BpbrGgrPTr3YJYRN3Bm+D9NuaFd+zGyNeIKgrhCXK60= +github.com/decred/dcrd/chaincfg/chainhash v1.0.3-0.20200921185235-6d75c7ec1199 h1:G6L0a9sBulqryyyWmin7cHorxfIdg2J+xHQeJaDdNyc= +github.com/decred/dcrd/chaincfg/chainhash v1.0.3-0.20200921185235-6d75c7ec1199/go.mod h1:BpbrGgrPTr3YJYRN3Bm+D9NuaFd+zGyNeIKgrhCXK60= github.com/decred/dcrd/chaincfg/v2 v2.0.2/go.mod h1:hpKvhLCDAD/xDZ3V1Pqpv9fIKVYYi11DyxETguazyvg= github.com/decred/dcrd/chaincfg/v2 v2.1.0/go.mod h1:hpKvhLCDAD/xDZ3V1Pqpv9fIKVYYi11DyxETguazyvg= github.com/decred/dcrd/chaincfg/v2 v2.2.0/go.mod h1:hpKvhLCDAD/xDZ3V1Pqpv9fIKVYYi11DyxETguazyvg= @@ -133,19 +197,19 @@ github.com/decred/dcrd/chaincfg/v2 v2.3.0/go.mod h1:7qUJTvn+y/kswSRZ4sT2+EmvlDTD github.com/decred/dcrd/chaincfg/v3 v3.0.0 h1:+TFbu7ZmvBwM+SZz5mrj6cun9ts/6DAL5sqnsaFBHGQ= github.com/decred/dcrd/chaincfg/v3 v3.0.0/go.mod h1:EspyubQ7D2w6tjP7rBGDIE7OTbuMgBjR2F2kZFnh31A= github.com/decred/dcrd/connmgr v1.0.1/go.mod h1:jR+woh3BTbP/35v0nHMiz6GfV1RO0uF1JA+mKeXNk04= -github.com/decred/dcrd/connmgr v1.0.2/go.mod h1:jBNfQLh+454n3crgNCPrhMgZ9mVvYcMbWSCEAHsJQus= github.com/decred/dcrd/connmgr/v3 v3.0.0/go.mod h1:cPI43Aggp1lOhrVG75eJ3c3BwuFx0NhT77FK34ky+ak= -github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/crypto/blake256 v1.0.1-0.20200921185235-6d75c7ec1199 h1:sqVg68MjCKwsahuL7AbbdkUSULnZF0vGFOM8FDGscjo= +github.com/decred/dcrd/crypto/blake256 v1.0.1-0.20200921185235-6d75c7ec1199/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/crypto/ripemd160 v1.0.0/go.mod h1:F0H8cjIuWTRoixr/LM3REB8obcWkmYx0gbxpQWR8RPg= github.com/decred/dcrd/crypto/ripemd160 v1.0.1 h1:TjRL4LfftzTjXzaufov96iDAkbY2R3aTvH2YMYa1IOc= github.com/decred/dcrd/crypto/ripemd160 v1.0.1/go.mod h1:F0H8cjIuWTRoixr/LM3REB8obcWkmYx0gbxpQWR8RPg= github.com/decred/dcrd/database v1.0.0/go.mod h1:eQOhTdO3oYBshjCVxMt747CP6yKKIls6IIdqYxMRzEk= github.com/decred/dcrd/database v1.0.1/go.mod h1:ILCeyOHFew3fZ7K2B9jl+tp5qFOap/pEGoo6Yy6Wk0g= +github.com/decred/dcrd/database v1.0.2 h1:/Q+1rxvCFUcFH3FfnzVXv+3NmVPoRZ3UQmqMr2KYReA= github.com/decred/dcrd/database v1.0.2/go.mod h1:ILCeyOHFew3fZ7K2B9jl+tp5qFOap/pEGoo6Yy6Wk0g= -github.com/decred/dcrd/database v1.0.3 h1:e5Q3gDt9LwfvpZxYqFF3OVzgr8bGeC1cen+V3mv/CCw= -github.com/decred/dcrd/database v1.0.3/go.mod h1:TLxRwIV8x85+dxPTLAWu4mHg45TkKrrza5xzwOS1QtA= github.com/decred/dcrd/database/v2 v2.0.0/go.mod h1:Sj2lvTRB0mfSu9uD7ObfwCY/eJ954GFU/X+AndJIyfE= +github.com/decred/dcrd/database/v2 v2.0.1/go.mod h1:ZOaWTv3IlNqCA+y7q3q5EozgmiDOmNwCSq3ntZn2CDo= github.com/decred/dcrd/database/v2 v2.0.2 h1:t1ch4sk2qIhxGcAmWQJkFwsbqKITEcVa8E+BFpxOf7s= github.com/decred/dcrd/database/v2 v2.0.2/go.mod h1:S78KbTCCJWUTJDVTByiQuB+HmL0DM2vIMsa2WsrF9KM= github.com/decred/dcrd/dcrec v0.0.0-20180721005212-59fe2b293f69/go.mod h1:cRAH1SNk8Mi9hKBc/DHbeiWz/fyO8KWZR3H7okrIuOA= @@ -154,14 +218,13 @@ github.com/decred/dcrd/dcrec v0.0.0-20180721031028-5369a485acf6/go.mod h1:cRAH1S github.com/decred/dcrd/dcrec v0.0.0-20180801202239-0761de129164/go.mod h1:cRAH1SNk8Mi9hKBc/DHbeiWz/fyO8KWZR3H7okrIuOA= github.com/decred/dcrd/dcrec v0.0.0-20180809193022-9536f0c88fa8/go.mod h1:cRAH1SNk8Mi9hKBc/DHbeiWz/fyO8KWZR3H7okrIuOA= github.com/decred/dcrd/dcrec v0.0.0-20180816212643-20eda7ec9229/go.mod h1:cRAH1SNk8Mi9hKBc/DHbeiWz/fyO8KWZR3H7okrIuOA= -github.com/decred/dcrd/dcrec v0.0.0-20181212181811-1a370d38d671/go.mod h1:cRAH1SNk8Mi9hKBc/DHbeiWz/fyO8KWZR3H7okrIuOA= -github.com/decred/dcrd/dcrec v1.0.0 h1:W+z6Es+Rai3MXYVoPAxYr5U1DGis0Co33scJ6uH2J6o= github.com/decred/dcrd/dcrec v1.0.0/go.mod h1:HIaqbEJQ+PDzQcORxnqen5/V1FR3B4VpIfmePklt8Q8= +github.com/decred/dcrd/dcrec v1.0.1-0.20200921185235-6d75c7ec1199 h1:MkfApk/KhuIh3llbjdnTFY5G4lb7zA+EEKVKIRgAfmg= +github.com/decred/dcrd/dcrec v1.0.1-0.20200921185235-6d75c7ec1199/go.mod h1:HIaqbEJQ+PDzQcORxnqen5/V1FR3B4VpIfmePklt8Q8= github.com/decred/dcrd/dcrec/edwards v0.0.0-20180721005212-59fe2b293f69/go.mod h1:+ehP0Hk/mesyZXttxCtBbhPX23BMpZJ1pcVBqUfbmvU= github.com/decred/dcrd/dcrec/edwards v0.0.0-20180721031028-5369a485acf6/go.mod h1:+ehP0Hk/mesyZXttxCtBbhPX23BMpZJ1pcVBqUfbmvU= github.com/decred/dcrd/dcrec/edwards v0.0.0-20180809193022-9536f0c88fa8/go.mod h1:+ehP0Hk/mesyZXttxCtBbhPX23BMpZJ1pcVBqUfbmvU= github.com/decred/dcrd/dcrec/edwards v0.0.0-20180816212643-20eda7ec9229/go.mod h1:+ehP0Hk/mesyZXttxCtBbhPX23BMpZJ1pcVBqUfbmvU= -github.com/decred/dcrd/dcrec/edwards v0.0.0-20181208004914-a0816cf4301f/go.mod h1:+ehP0Hk/mesyZXttxCtBbhPX23BMpZJ1pcVBqUfbmvU= github.com/decred/dcrd/dcrec/edwards v1.0.0 h1:UDcPNzclKiJlWqV3x1Fl8xMCJrolo4PB4X9t8LwKDWU= github.com/decred/dcrd/dcrec/edwards v1.0.0/go.mod h1:HblVh1OfMt7xSxUL1ufjToaEvpbjpWvvTAUx4yem8BI= github.com/decred/dcrd/dcrec/edwards/v2 v2.0.0/go.mod h1:d0H8xGMWbiIQP7gN3v2rByWUcuZPm9YsgmnfoxgbINc= @@ -174,17 +237,15 @@ github.com/decred/dcrd/dcrec/secp256k1 v1.0.2/go.mod h1:CHTUIVfmDDd0KFVFpNX1pFVC github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.0/go.mod h1:3s92l0paYkZoIHuj4X93Teg/HB7eGM9x/zokGw+u4mY= github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0 h1:sgNeV1VRMDzs6rzyPpxyM0jp317hnwiq58Filgag2xw= github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0/go.mod h1:J70FGZSbzsjecRTiTzER+3f1KZLNaXkuv+yeFTKoxM8= +github.com/decred/dcrd/dcrjson v1.0.0 h1:50DnA0XeV2JrQXoHh43TCKmH+kz2gHjZ1Mj/Pdk7Oz0= github.com/decred/dcrd/dcrjson v1.0.0/go.mod h1:ozddIaeF+EAvZZvFuB3zpfxhyxBGfvbt22crQh+PYuI= -github.com/decred/dcrd/dcrjson v1.1.0 h1:pFpbay3cWACkgloFxWjHBwlXWG2+S2QCJJzNxL40hwg= -github.com/decred/dcrd/dcrjson v1.1.0/go.mod h1:ozddIaeF+EAvZZvFuB3zpfxhyxBGfvbt22crQh+PYuI= github.com/decred/dcrd/dcrjson/v3 v3.0.0/go.mod h1:pWYlHJ3VFidPwqD5HHiJXjfGaplif8uspAL2qFdifkY= +github.com/decred/dcrd/dcrjson/v3 v3.0.1/go.mod h1:fnTHev/ABGp8IxFudDhjGi9ghLiXRff1qZz/wvq12Mg= github.com/decred/dcrd/dcrjson/v3 v3.1.0 h1:Y2VjCXCNWbNIa52wMKEuNiU+9rUgnjYb5c1JQW6PuzM= github.com/decred/dcrd/dcrjson/v3 v3.1.0/go.mod h1:fnTHev/ABGp8IxFudDhjGi9ghLiXRff1qZz/wvq12Mg= github.com/decred/dcrd/dcrutil v1.0.0/go.mod h1:CBpbItyMKkL/4i1qPJDsE/cdSYklsWFcTYgprRZh4yk= +github.com/decred/dcrd/dcrutil v1.1.1 h1:zOkGiumN/JkobhAgpG/zfFgUoolGKVGYT5na1hbYUoE= github.com/decred/dcrd/dcrutil v1.1.1/go.mod h1:Jsttr0pEvzPAw+qay1kS1/PsbZYPyhluiNwwY6yBJS4= -github.com/decred/dcrd/dcrutil v1.2.0/go.mod h1:tUNHS2gj7ApeEVS8gb6O+4wJW7w3O2MSRyRdcjW1JxU= -github.com/decred/dcrd/dcrutil v1.4.0 h1:xD5aUqysGQnsnP1c9J0kGeW8lDIwFGC3ja/gE3HnpCs= -github.com/decred/dcrd/dcrutil v1.4.0/go.mod h1:Bs74gm1jQ9ZAbmEh9FWOEZ1HQzlMg5iPATDMzMnCMlQ= github.com/decred/dcrd/dcrutil/v2 v2.0.0/go.mod h1:gUshVAXpd51DlcEhr51QfWL2HJGkMDM1U8chY+9VvQg= github.com/decred/dcrd/dcrutil/v2 v2.0.1/go.mod h1:JdEgF6eh0TTohPeiqDxqDSikTSvAczq0J7tFMyyeD+k= github.com/decred/dcrd/dcrutil/v3 v3.0.0 h1:n6uQaTQynIhCY89XsoDk2WQqcUcnbD+zUM9rnZcIOZo= @@ -194,33 +255,33 @@ github.com/decred/dcrd/gcs v1.0.1/go.mod h1:YwutGzusSdJM79CJtxCo9t7WRCvnkLtWSD19 github.com/decred/dcrd/gcs v1.0.2/go.mod h1:eLCvrzUsWro48TlTyrmFcZAZqnllYFz0vEv5VZtufF4= github.com/decred/dcrd/gcs v1.1.0 h1:djuYzaFUzUTJR+6ulMSRZOQ+P9rxtIyuxQeViAEfB8s= github.com/decred/dcrd/gcs v1.1.0/go.mod h1:yBjhj217Vw5lw3aKnCdHip7fYb9zwMos8bCy5s79M9w= +github.com/decred/dcrd/gcs/v2 v2.0.0/go.mod h1:3XjKcrtvB+r2ezhIsyNCLk6dRnXRJVyYmsd1P3SkU3o= github.com/decred/dcrd/gcs/v2 v2.1.0 h1:foECqwfE3UJztU4CYtqUYqvR254x1Z9clXVfNdOjBQ8= github.com/decred/dcrd/gcs/v2 v2.1.0/go.mod h1:MbnJOINFcp42NMRAQ+CjX/xGz+53AwNgMzKZhwBibdM= +github.com/decred/dcrd/hdkeychain v1.1.0 h1:6bFdL672dCmtg/JEzb3Jw0dTRO2jLxcA7BK2J+JaoUM= github.com/decred/dcrd/hdkeychain v1.1.0/go.mod h1:zyUZtZ3PdnTPHt2XUr1x76b8ZuiM+9aVkP8Rq8Scp1k= -github.com/decred/dcrd/hdkeychain v1.1.1 h1:6+BwOmPfEyw/Krm+91RXysc76F1jqCta3m45DyD5+s4= -github.com/decred/dcrd/hdkeychain v1.1.1/go.mod h1:CLBVXLoO63fIiqkv38KR23zXGSgrfiAWOybOKTneLhA= github.com/decred/dcrd/hdkeychain/v2 v2.0.1/go.mod h1:qPv+vTla19liVHFuXVnQ70dMI4ERPCniDXbV5RzwQiM= +github.com/decred/dcrd/hdkeychain/v2 v2.1.0/go.mod h1:DR+lD4uV8G0i3c9qnUJwjiGaaEWK+nSrbWCz1BRHBL8= github.com/decred/dcrd/hdkeychain/v3 v3.0.0 h1:hOPb4c8+K6bE3a/qFtzt2Z2yzK4SpmXmxvCTFp8vMxI= github.com/decred/dcrd/hdkeychain/v3 v3.0.0/go.mod h1:Vz7PJSlLzhqmOR2lmjGD9JqAZgmUnM8P6r8hg7U4Zho= github.com/decred/dcrd/mempool v1.0.1/go.mod h1:r+/DGiiluXi1EyMCCPPH58Qu+rsr8nZv0DialAG5VZQ= -github.com/decred/dcrd/mempool v1.1.1/go.mod h1:u1I2KRv9UHhx2crlbZXYoLDabWyQ8VnnHDSG53UdhCA= github.com/decred/dcrd/mining v1.0.0/go.mod h1:VA5H4zhJgXb8LK5lqM5H58dhMRXJRcaQQoX3G8QRpP8= github.com/decred/dcrd/mining v1.0.1/go.mod h1:+CSOLPi7TM8OlQg7mJ7XzWLXCDb4nHK8R6cvXOzhEoU= -github.com/decred/dcrd/mining v1.1.0/go.mod h1:NQEtX604XgNwKcPFId1hVTTiBqmVQDlnqV1yNqGl4oU= -github.com/decred/dcrd/rpc/jsonrpc/types v1.0.0 h1:d5ptnjuSADTQMa3i83VpeJNoMRTOJZZBqk7P+E41VXM= github.com/decred/dcrd/rpc/jsonrpc/types v1.0.0/go.mod h1:0dwmpIP21tJxjg/UuUHWIFMbfoLv2ifCBMokNKlOxpo= +github.com/decred/dcrd/rpc/jsonrpc/types v1.0.1 h1:sWsGtWzdmrna6aysDCHwjANTJh+Lxt2xp6S10ahP79Y= +github.com/decred/dcrd/rpc/jsonrpc/types v1.0.1/go.mod h1:dJUp9PoyFYklzmlImpVkVLOr6j4zKuUv66YgemP2sd8= +github.com/decred/dcrd/rpc/jsonrpc/types/v2 v2.0.0/go.mod h1:c5S+PtQWNIA2aUakgrLhrlopkMadcOv51dWhCEdo49c= github.com/decred/dcrd/rpc/jsonrpc/types/v2 v2.3.0 h1:KZ2zihwY5Mx6EeYwEA3bL3k+qDXdCraQL+iDIG1BP5k= github.com/decred/dcrd/rpc/jsonrpc/types/v2 v2.3.0/go.mod h1:krn89ZOgSa8yc7sA4WpDK95p61NnjNWFkNlMnGrKbMc= +github.com/decred/dcrd/rpcclient v1.0.1 h1:mSkVtOQKXnMJ2P08xPFnD2J9w54+YFQuMeBd5tC9iBI= github.com/decred/dcrd/rpcclient v1.0.1/go.mod h1:tApXK3wwrAQtz7lcXeeqBwuktUZesvrFfvhAdedYqdM= -github.com/decred/dcrd/rpcclient v1.1.0 h1:nQZ1qOJaLYoOTM1oQ2dLaqocb5TWI7gNBK+BTY7UVXk= -github.com/decred/dcrd/rpcclient v1.1.0/go.mod h1:SCwBs4d+aqRV2ChnriIZ1y/LgNVHG/2ieEC1vIop82s= github.com/decred/dcrd/rpcclient/v4 v4.0.0/go.mod h1:DNGwfiL5H+K/pk3hVB0z5ypRdiDXMssR+YEqDUEXCQo= +github.com/decred/dcrd/rpcclient/v5 v5.0.0/go.mod h1:lg7e2kpulSpynHkS2JXJ+trQ4PWHaHLQcp/Q0eSIvBc= github.com/decred/dcrd/rpcclient/v6 v6.0.2 h1:bPHPeKGrPZPsHDSRIJxj5xhqoxwM5R7+OsEZXFpDxPk= github.com/decred/dcrd/rpcclient/v6 v6.0.2/go.mod h1:t6ECC72j2xWQ323poL85IFNq0EUfcSTfwL8j7jDJ6mw= github.com/decred/dcrd/txscript v1.0.0/go.mod h1:9byvrOaBSBVVnDG7Cm0JgN8bZytl1oi9Ba245VBeI18= +github.com/decred/dcrd/txscript v1.0.1 h1:IMgxZFCw3AyG4EbKwywE3SDNshOSHsoUK1Wk/5GqWJ0= github.com/decred/dcrd/txscript v1.0.1/go.mod h1:FqUX07Y+u3cJ1eIGPoyWbJg+Wk1NTllln/TyDpx9KnY= -github.com/decred/dcrd/txscript v1.0.2 h1:kzJZDuteyzvI15VNhtgFHxeeq210RTkFyfzN7d+1iPo= -github.com/decred/dcrd/txscript v1.0.2/go.mod h1:hmUOHFlOjU7H6T/czt6kurWwXJvGPGKKGtXoft6w/qY= github.com/decred/dcrd/txscript/v2 v2.0.0/go.mod h1:WStcyYYJa+PHJB4XjrLDRzV96/Z4thtsu8mZoVrU6C0= github.com/decred/dcrd/txscript/v2 v2.1.0/go.mod h1:XaJAVrZU4NWRx4UEzTiDAs86op1m8GRJLz24SDBKOi0= github.com/decred/dcrd/txscript/v3 v3.0.0 h1:74NmirXAIskbGP0g9OWtrmN7OxDbWJ9G73a5uoxTkcM= @@ -231,75 +292,46 @@ github.com/decred/dcrd/wire v1.2.0/go.mod h1:/JKOsLInOJu6InN+/zH5AyCq3YDIOW/Eqcf github.com/decred/dcrd/wire v1.3.0/go.mod h1:fnKGlUY2IBuqnpxx5dYRU5Oiq392OBqAuVjRVSkIoXM= github.com/decred/dcrd/wire v1.4.0 h1:KmSo6eTQIvhXS0fLBQ/l7hG7QLcSJQKSwSyzSqJYDk0= github.com/decred/dcrd/wire v1.4.0/go.mod h1:WxC/0K+cCAnBh+SKsRjIX9YPgvrjhmE+6pZlel1G7Ro= -github.com/decred/dcrdata/api/types/v4 v4.0.2/go.mod h1:9Jnyp9FLSfhx7jlJSyKJaeOJ/33LAOL+uvE1T0bcOns= github.com/decred/dcrdata/api/types/v4 v4.0.4/go.mod h1:CCu2Itqv/K3lqFxqSYDC49XWu5OuZRvNFkPiFHb0tYU= -github.com/decred/dcrdata/blockdata/v4 v4.0.4-0.20191018131105-43d40fcf6525/go.mod h1:P8HsR6L6RuYyuJNFRxke4X67YeJ91rOBeSAb8ZI0jJ8= -github.com/decred/dcrdata/db/dbtypes/v2 v2.1.2/go.mod h1:Gb3NmWxL+3nsy9f7kmnLXwVUmHp0oHtn+WblrKIM3DM= -github.com/decred/dcrdata/db/dbtypes/v2 v2.1.3-0.20191018131657-8f5538d3b4b3/go.mod h1:F0BY7RbDsTFUfPOK/q9NkubZfKt7LxD06wCCvC5gywU= github.com/decred/dcrdata/db/dbtypes/v2 v2.1.4/go.mod h1:UF4KWxcCYhdXqaTwbA2Mb10os4H0UFSZaiu5eeMWQT8= -github.com/decred/dcrdata/dcrrates v1.1.1/go.mod h1:r/d8jU/E1rA+hska5xMmkpsyUzMupLGuTxXQ9GhBD7Y= -github.com/decred/dcrdata/exchanges/v2 v2.0.2/go.mod h1:VZhPe44SLhhbQSniNUwv/CNYwgghPzBRNXRPNljby6g= -github.com/decred/dcrdata/explorer/types/v2 v2.0.2/go.mod h1:6cvEUaSYkyGoiqgyh/3N2I2EzXjb6TRBact3yi8Gtdo= -github.com/decred/dcrdata/explorer/types/v2 v2.0.3-0.20191018131657-8f5538d3b4b3/go.mod h1:ibWnzMcQkoE547UD0LI29i5v5jaoyKpeLeU7Cd5tIkY= -github.com/decred/dcrdata/mempool/v4 v4.0.4-0.20191018131657-8f5538d3b4b3/go.mod h1:ysaPY8oraR1Hv+xTaTeF6QK9TaGDC5eS56KN7AAd7+Y= -github.com/decred/dcrdata/pubsub/types/v3 v3.0.2/go.mod h1:Rycd3SPR2dC9WIBQhnWFqta7uRK9yKqJDz70jz880no= -github.com/decred/dcrdata/pubsub/types/v3 v3.0.3-0.20191018131657-8f5538d3b4b3/go.mod h1:/NDVANaxXK2Fvq1+WPsezNmMniA5G2iZHtLF9DKTK2E= -github.com/decred/dcrdata/pubsub/types/v3 v3.0.3-0.20191018133341-23a17268b383/go.mod h1:/NDVANaxXK2Fvq1+WPsezNmMniA5G2iZHtLF9DKTK2E= -github.com/decred/dcrdata/pubsub/v3 v3.0.4-0.20191018133341-23a17268b383/go.mod h1:bSYDdKxj5tUA31Jm9HpmyPg/YR6qERSrQH81gPpyOj0= -github.com/decred/dcrdata/rpcutils/v2 v2.0.3/go.mod h1:bN6Mwdd1udV0/0QJiYOG10ChEao1FFnM5TBeoF43mu8= +github.com/decred/dcrdata/db/dbtypes/v2 v2.2.1/go.mod h1:zVQdtnKZqlmop/C+qCb1vGU9ab3CGC6gohM+AWTQbYg= github.com/decred/dcrdata/semver v1.0.0/go.mod h1:z+nQqiAd9fYkHhBLbejysZ2FPHtgkrErWDgMf+JlZWE= -github.com/decred/dcrdata/stakedb/v3 v3.0.4-0.20191016213257-fb798036d9dc/go.mod h1:8oDaFvlGbOocULLymbQ40Ju7qQgfPRbIyV5wxUFFHL0= -github.com/decred/dcrdata/txhelpers/v3 v3.0.2/go.mod h1:iukqEl5AR6BdippUWKsC8OzaV9TW/KMBYpIwKv8IkW0= -github.com/decred/dcrdata/txhelpers/v3 v3.0.3-0.20191018131657-8f5538d3b4b3/go.mod h1:t/5u8aHI2Z/ey6SQ3G0/jGwPweUz/uojF2dT2ePpmEw= github.com/decred/dcrdata/txhelpers/v3 v3.0.4/go.mod h1:tKEDhoO+TbYrFrx+5qKZDxcla8ELQFYs4f5+8gL4cuY= +github.com/decred/dcrdata/txhelpers/v4 v4.0.1/go.mod h1:cUJbgsIzzI42llHDS0nkPlG49vPJ0cW6IZGbfu5sFrA= +github.com/decred/dcrtime v0.0.0-20191018193024-8d8b4ef0458e h1:sNDR7vx6gaA3WD+WoEofTvtdjfwHAiogtjB3kt8iFco= github.com/decred/dcrtime v0.0.0-20191018193024-8d8b4ef0458e/go.mod h1:IyZnyBE3E6RBFsEjwEs21FrO/UsrLrL15hUnpZZQxpU= +github.com/decred/dcrtime/api/v2 v2.0.0-20200912200806-b1e4dbc46be9/go.mod h1:JdIX208vnNj4TdU6hDRaN+ccxmxp1I1R6sWGZNK1BAQ= github.com/decred/dcrwallet v1.2.2/go.mod h1:BrSus0F+Rx8UhvPNBfuRMIjRJBNrW2sLspN9iQR5hm8= -github.com/decred/dcrwallet v1.2.3-0.20190128160919-849f7c01c12d/go.mod h1:jtNUWAO6lg2t2UHOlT9fmjuxD8os9JMljZNEXaw95Tg= github.com/decred/dcrwallet/chain v1.0.0/go.mod h1:KpZFaKlKajfUZt36+RmBn2HKwTbwoa3yt9HPALqlShI= -github.com/decred/dcrwallet/chain v1.1.1/go.mod h1:2kA82rBDkCKOSYFV+Q14RZNCuYwdaQ9uO/c+RixqRNs= github.com/decred/dcrwallet/deployments v1.0.0/go.mod h1:0bWER/DAYoGbzkWzbUf6k2agW4YkSyvNLZDhBGThz/4= -github.com/decred/dcrwallet/deployments v1.1.0/go.mod h1:8Sasryu8SX23Jvqr6maZ7MoS7wFIGXupWzbsVtcZsUg= github.com/decred/dcrwallet/errors v1.0.0/go.mod h1:XUm95dWmm9XmQGvneBXJkkIaFeRsQVBB6ni/KTy1hrY= -github.com/decred/dcrwallet/errors v1.0.1/go.mod h1:XUm95dWmm9XmQGvneBXJkkIaFeRsQVBB6ni/KTy1hrY= github.com/decred/dcrwallet/internal/helpers v1.0.0/go.mod h1:FsihtjCyFrGL6gdmkxBWTYQ1CUgbfM9tyinYNOzLnlk= -github.com/decred/dcrwallet/internal/helpers v1.0.1/go.mod h1:qIXcze8VZ+A3sEgZou7PTOe4Vsnmks54SGTSGZ6084g= github.com/decred/dcrwallet/internal/zero v1.0.0/go.mod h1:vULuNLRTcnifKCepcIxUDL4jrR3rJOwVR9UDH89Qpms= -github.com/decred/dcrwallet/internal/zero v1.0.1/go.mod h1:mXUIsKATE1pIaNAJQ4lhSTX6c9N5sYoSrlScgRCaMJs= github.com/decred/dcrwallet/lru v1.0.0/go.mod h1:jEty7mdT5VaaV06DEV2Avv0R3HpGvUwvDW4lw8ECtiY= github.com/decred/dcrwallet/p2p v1.0.0/go.mod h1:b1CLZAkl/K5dr5I5B4SdFT8FrE11jSkfA4VAA862ACA= -github.com/decred/dcrwallet/p2p v1.0.1/go.mod h1:FsoAR0cBOLW3VKMg+Tdx+wdSezR7g8NGOdz4fx6gtpM= github.com/decred/dcrwallet/pgpwordlist v1.0.0/go.mod h1:Fek3uYn+9DnEFIreA/8PnTIXUl2lBO64JpEBkL9BXtk= github.com/decred/dcrwallet/rpc/jsonrpc/types v1.1.0/go.mod h1:xUT7XXATLOzE0pwwmvgfRWtZdrB+PsWFilo+jkH5/Ig= +github.com/decred/dcrwallet/rpc/jsonrpc/types v1.3.0/go.mod h1:Xvekb43GtfMiRbyIY4ZJ9Uhd9HRIAcnp46f3q2eIExU= github.com/decred/dcrwallet/rpc/walletrpc v0.1.0/go.mod h1:Zp1ZFTCUo7S6MJvUyS5tYfaDUxGAMHkZ+vbsLgAdd4A= github.com/decred/dcrwallet/rpc/walletrpc v0.2.0/go.mod h1:uhjgcju9lSb/+42Ms4VY1zpBOxstCLM5wVlL3mq/SYc= github.com/decred/dcrwallet/spv v1.0.0/go.mod h1:lz39nz9P/HVoxYa4XAT6ithyR3WgdF0oVu4jtFwnCxE= -github.com/decred/dcrwallet/spv v1.1.0/go.mod h1:HYfF+A1F+Apf0WPT6QRsG/gfvaFQmWObAytq8pWc6ME= github.com/decred/dcrwallet/ticketbuyer v1.0.0/go.mod h1:mrAlRjOJ6txO8Zyqo5koxVOMEYLK2POUX35a/QcKN8g= -github.com/decred/dcrwallet/ticketbuyer v1.0.2/go.mod h1:oDHY0TOFIaQjZ11TJbgztC5tt1zi6wKoRmyQMmwfft4= github.com/decred/dcrwallet/ticketbuyer/v2 v2.0.0/go.mod h1:VKo2PjXAlF/E46tSBKrIgqKbVcHVLfM5ACyOehT1unA= -github.com/decred/dcrwallet/ticketbuyer/v2 v2.0.1/go.mod h1:ngtx8I/+Jo+U+E/5XjwCkmU55wCGtUbaDnCP5qazNGM= github.com/decred/dcrwallet/validate v1.0.0/go.mod h1:zHIlcrjAWl6LK+X+R7jc3F9wIM/qxjtMjG/mdEwt4tY= github.com/decred/dcrwallet/validate v1.0.1/go.mod h1:9DCtLFnnTOC/7PKkF7jehvDyHkfUBl41ZbcT1u4PmQM= -github.com/decred/dcrwallet/validate v1.0.2/go.mod h1:1ur2sRZkQ23ECalUKdwgx6rdIiP8rIiaSQAz1Y9LQsI= github.com/decred/dcrwallet/version v1.0.0/go.mod h1:rXeMsUaI03WtlQrSol7Q7sJ8HBOB+tZvT7YQRXD5Y7M= -github.com/decred/dcrwallet/version v1.0.1/go.mod h1:rXeMsUaI03WtlQrSol7Q7sJ8HBOB+tZvT7YQRXD5Y7M= github.com/decred/dcrwallet/wallet v1.0.0/go.mod h1:VWRnpNFRiKPo7FUPbzj0t5ElcGxNXMPIa4vGcGe94uM= -github.com/decred/dcrwallet/wallet v1.1.0/go.mod h1:g4OzDG7jpsRqTDP3bHiA0LIEZFx81accYPCkO1DBNT8= -github.com/decred/dcrwallet/wallet v1.2.0/go.mod h1:ItOhnw3C4znuLQVWACSq8jCLy221v9X0Xo0b/j5WqgU= -github.com/decred/dcrwallet/wallet v1.3.0/go.mod h1:ItOhnw3C4znuLQVWACSq8jCLy221v9X0Xo0b/j5WqgU= github.com/decred/dcrwallet/walletseed v1.0.0/go.mod h1:xSF6hZW+5Xhm0jJFsI5jQSfViuZUQJoDXa/cQxtgncs= -github.com/decred/dcrwallet/walletseed v1.0.1/go.mod h1:ENlwTabC2JVmT4S1eCP44fnwX4+9y2RLsnfSU21CJ+4= github.com/decred/go-socks v1.0.0/go.mod h1:sDhHqkZH0X4JjSa02oYOGhcGHYp12FsY1jQ/meV8md0= github.com/decred/go-socks v1.1.0 h1:dnENcc0KIqQo3HSXdgboXAHgqsCIutkqq6ntQjYtm2U= github.com/decred/go-socks v1.1.0/go.mod h1:sDhHqkZH0X4JjSa02oYOGhcGHYp12FsY1jQ/meV8md0= -github.com/decred/politeia v0.0.0-20191031182202-b33af07598f2 h1:xF5UazYefAzh91yvD6Rv6zkogZb+kJyIhx8mX89giuE= -github.com/decred/politeia v0.0.0-20191031182202-b33af07598f2/go.mod h1:biL6LECQ+6xwYHEJocudqMK+A1O0XbBshFkvFziFZgg= +github.com/decred/politeia v1.0.1 h1:MehAIlMLZZBLlkP8LuAlckx0xmIpIZJTYkXOkRGxdA8= +github.com/decred/politeia v1.0.1/go.mod h1:bWvCogzo8MzyPos4tX9V/5FXhVRUwcd6ycZhElcDLE0= github.com/decred/slog v1.0.0/go.mod h1:zR98rEZHSnbZ4WHZtO0iqmSZjDLKhkXfrPTZQKtAonQ= github.com/decred/slog v1.1.0 h1:uz5ZFfmaexj1rEDgZvzQ7wjGkoSPjw2LCh8K+K1VrW4= github.com/decred/slog v1.1.0/go.mod h1:kVXlGnt6DHy2fV5OjSeuvCJ0OmlmTF6LFpEPMu/fOY0= -github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM= +github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= -github.com/dgraph-io/badger v1.5.5-0.20190214192501-3196cc1d7a5f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= github.com/dgraph-io/badger v1.6.2 h1:mNw0qs90GVgGGWylh0umH5iag1j6n/PeJtNvL6KY/x8= github.com/dgraph-io/badger v1.6.2/go.mod h1:JW2yswe3V058sS0kZ2h/AXeDSqFjxnZcRrVH//y2UQE= github.com/dgraph-io/ristretto v0.0.2 h1:a5WaUrDa0qm0YrAAS1tUykT5El3kt62KNZZeMxQn3po= @@ -309,24 +341,29 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczC github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/didip/tollbooth/v6 v6.1.0 h1:ZS2fNa9JhFdRSJCj3+V12VfuUifYrGB4Z0jSwXmKMeE= github.com/didip/tollbooth/v6 v6.1.0/go.mod h1:xjcse6CTHCLuOkzsWrEgdy9WPJFv+p/x6v+MyfP+O9s= -github.com/dmigwi/go-piparser/proposals v0.0.0-20191219171828-ae8cbf4067e1 h1:8+y5flqx5OCcYOuzKGnUS1PluG9hexfL5I3IAN4aym4= -github.com/dmigwi/go-piparser/proposals v0.0.0-20191219171828-ae8cbf4067e1/go.mod h1:bVFHMc7PF69eSpDREy2MnoZYr8YMQjGDEUJudtQUEis= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elazarl/goproxy v0.0.0-20181111060418-2ce16c963a8a/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.0.14/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fullstorydev/grpcurl v1.6.0/go.mod h1:ZQ+ayqbKMJNhzLmbpCiurTVlaK2M/3nqZCxaQ2Ze/sM= github.com/gcash/bchd v0.14.7/go.mod h1:Gk/O1ktRVW5Kao0RsnVXp3bWxeYQadqawZ1Im9HE78M= github.com/gcash/bchd v0.15.2/go.mod h1:k9wIjgwnhbrAw+ruIPZ2tHZMzfFNdyUnORZZX7lqXGY= github.com/gcash/bchd v0.17.2-0.20201218180520-5708823e0e99/go.mod h1:qwEZ/wr6LyUo5IBgAPcAbYHzXrjnr5gc4tj03n1TwKc= @@ -343,31 +380,54 @@ github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITL github.com/go-chi/docgen v1.2.0 h1:da0Nq2PKU9W9pSOTUfVrKI1vIgTGpauo9cfh4Iwivek= github.com/go-chi/docgen v1.2.0/go.mod h1:G9W0G551cs2BFMSn/cnGwX+JBHEloAgo17MBhyrnhPI= github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= github.com/go-pkgz/expirable-cache v0.0.3 h1:rTh6qNPp78z0bQE6HDhXBHUwqnV9i09Vm6dksJLXQDc= github.com/go-pkgz/expirable-cache v0.0.3/go.mod h1:+IauqN00R2FqNRLCLA+X5YljQJrwB179PfiAoMPlTlQ= github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= +github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -381,59 +441,106 @@ github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8l github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gops v0.3.17 h1:CguOcnDVYG32soOj2YevV8mW9asrIh1lZw3d7Ovty/o= github.com/google/gops v0.3.17/go.mod h1:Pfp8hWGIFdV/7rY9/O/U5WgdjYQXf/GiEK4NVuVd2ZE= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/trillian v1.2.1/go.mod h1:YPmUVn5NGwgnDUgqlVyFGMTgaWlnSvH7W5p+NdOG8UA= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200507031123-427632fa3b1c/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/trillian v1.3.13 h1:V0avmojBPY7YAlcd/nUVvNRprU28tRsahPNxIedqekU= +github.com/google/trillian v1.3.13/go.mod h1:8y3zC8XuqFxsslWPkP0r3sprERfFf7hCWmicL0yHZNI= +github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googollee/go-socket.io v1.4.4 h1:UWOy//wzcT1ENMDeeVsrXwcCY49XOvC/YHVMZJDfy9M= github.com/googollee/go-socket.io v1.4.4/go.mod h1:2lMkHRm5GLg158lACi6Zj6535AQaXuyA+IKbfqKzTOM= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/csrf v1.6.0/go.mod h1:7tSf8kmjNYr7IWDCYhd3U8Ck34iQ/Yw5CJu7bAkHEGI= +github.com/gorilla/csrf v1.6.2/go.mod h1:7tSf8kmjNYr7IWDCYhd3U8Ck34iQ/Yw5CJu7bAkHEGI= github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY= github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= -github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.3/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c h1:fEE5/5VNnYUoBOj2I9TP8Jc+a7lge3QWn9DKE7NCwfc= github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c/go.mod h1:ObS/W+h8RYb1Y7fYivughjxojTmIu5iAIjSrSLCLeqE= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= +github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/improbable-eng/grpc-web v0.9.1/go.mod h1:6hRR09jOEG81ADP5wCQju1z71g6OL4eEvELdran/3cs= github.com/improbable-eng/grpc-web v0.13.0/go.mod h1:6hRR09jOEG81ADP5wCQju1z71g6OL4eEvELdran/3cs= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v0.0.0-20181221193153-c0795c8afcf4/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.1-0.20200711081900-c17162fe8fd7 h1:Ug59miTxVKVg5Oi2S5uHlKOIV5jBx4Hb2u0jIxxDaSs= github.com/jessevdk/go-flags v1.4.1-0.20200711081900-c17162fe8fd7/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jinzhu/gorm v1.9.10/go.mod h1:Kh6hTsSGffh4ui079FHrR5Gg+5D0hgihqDcsDN2BBJY= +github.com/jhump/protoreflect v1.6.1/go.mod h1:RZQ/lnuN+zqeRVpQigTwO6o0AJUkxbnSnpuG7toUTG4= +github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZT/Qs= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jrick/bitset v1.0.0/go.mod h1:ZOYB5Uvkla7wIEY4FEssPVi3IQXa02arznRaYaAEPe4= github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= @@ -441,17 +548,23 @@ github.com/jrick/wsrpc/v2 v2.3.2/go.mod h1:XPYs8BnRWl99lCvXRM5SLpZmTPqWpSOPkDIqY github.com/jrick/wsrpc/v2 v2.3.4/go.mod h1:XPYs8BnRWl99lCvXRM5SLpZmTPqWpSOPkDIqYTwDPfU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19/go.mod h1:hY+WOq6m2FpbvyrI93sMaypsttvaIL5nhVR92dTMUcQ= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/kkdai/bstream v0.0.0-20181106074824-b3251f7901ec/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= @@ -460,36 +573,76 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.2/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= +github.com/letsencrypt/pkcs11key/v4 v4.0.0/go.mod h1:EFUvBDay26dErnNb70Nd0/VW3tJiIbETBPTl9ATXQag= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.1 h1:6VXZrLU0jHBYyAqrSPa+MgPfnSvTPuMgK+k0o5kVFWo= github.com/lib/pq v1.10.1/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/marcopeereboom/sbox v1.0.0/go.mod h1:V9e7t7oKphNfXymk7Lqvbo9mZiVjmCt8vBHnROcpCSY= +github.com/marcopeereboom/sbox v1.1.0 h1:IiVHCi5f+nGRiMX551wnDk5ce+IEd3dWVH7ycf2uU2M= +github.com/marcopeereboom/sbox v1.1.0/go.mod h1:u2fh4EbQDXQXXzGypWkf2nMn2TnsqA23t224mii7oog= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007/go.mod h1:m2XC9Qq0AlmmVksL6FktJCdTYyLk7V3fKyp0sl1yWQo= +github.com/mwitkow/go-proto-validators v0.2.0/go.mod h1:ZfA1hW+UH/2ZHOWvQ3HnQaU0DtnpXu850MZiy+YUgcc= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/nishanths/predeclared v0.0.0-20190419143655-18a43bb90ffc/go.mod h1:62PewwiQTlm/7Rj+cxVYqZvDIUc+JjZq6GHAC1fsObQ= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= @@ -500,63 +653,106 @@ github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/otiai10/copy v1.0.1/go.mod h1:8bMCJrAqOtN/d9oyh5HR7HhLQMvcGMpGdwRDYsfOCHc= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v0.0.0-20190513014714-f5a3d24e5776/go.mod h1:3HNVkVOU7vZeFXocWuvtcS0XSFLcf2XUSDHkq9t1jU4= github.com/otiai10/mint v1.2.3/go.mod h1:YnfyPNhBvnY8bW4SGQHCs/aAFhkgySlMZbrF5U0bOVw= github.com/otiai10/mint v1.2.4/go.mod h1:d+b7n/0R3tdyUYYylALXpWQ/kTN+QobSq/4SRGBkR3M= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/pseudomuto/protoc-gen-doc v1.3.2/go.mod h1:y5+P6n3iGrbKG+9O04V5ld71in3v/bX88wUwgt+U8EA= +github.com/pseudomuto/protokit v0.2.0/go.mod h1:2PdH30hxVHsup8KpBTOXTBeMVhJZVio3Q8ViKSAXT0Q= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d h1:1VUlQbCfkoSGv7qP7Y+ro3ap1P1pPZxgdGVqiTVy5C4= github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.7.1-0.20201213214713-f9bce55a4e61 h1:ShPDRmLRZM1dY///S8mO6XIvcf8zzJ5bTnEsPbHCGxY= github.com/rs/cors v1.7.1-0.20201213214713-f9bce55a4e61/go.mod h1:EBwu+T5AvHOcXwvZIkQFjUN6s8Czyqw12GL/Y0tUyRM= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shirou/gopsutil/v3 v3.21.2/go.mod h1:ghfMypLDrFSWN2c9cDYFLHyynQ+QUht0cv/18ZqVczw= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v0.0.0-20170130113145-4d4bfba8f1d1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -570,41 +766,63 @@ github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca h1:Ld/zXl5t4+D6 github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/tklauser/go-sysconf v0.3.4/go.mod h1:Cl2c8ZRWfHD5IrfHo9VN+FX9kCFjIOyVklgXycLB6ek= github.com/tklauser/numcpus v0.2.1/go.mod h1:9aU+wOc6WjUIZEwWMP62PL/41d65P+iks1gBkr4QyP8= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= -github.com/vmihailenco/msgpack v4.0.1+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v1.0.0/go.mod h1:IoImgRak9i3zJyuxOKUP1v4UZd1tMoKkq/Cimt1uhCg= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zquestz/grab v0.0.0-20190224022517-abcee96e61b1/go.mod h1:bslhAiUxakrA6z6CHmVyvkfpnxx18RJBwVyx2TluJWw= -go.etcd.io/bbolt v1.3.0/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200819165624-17cef6e3e9d5/go.mod h1:skWido08r9w6Lq/w70DO5XYIKMu4QFu1+4VsqLQuJy8= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180501155221-613d6eafa307/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180718160520-a2144134853f/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180808211826-de0752318171/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -614,16 +832,44 @@ golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180808004115-f9ce57c11b24/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181207154023-610586996380/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -631,16 +877,28 @@ golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190415214537-1da14a5a36f2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191105084925-a882066a44e0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201022231255-08b38378de70/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201024042810-be3efd7ff127/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -649,106 +907,227 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180810070207-f0d5e33068cb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180816055513-1c9583448a9c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181206074257-70b957f3b65e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181212120007-b05ddf57801d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190416124237-ebb4019f01c9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190614084037-d442b75600c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201022201747-fb209a7c41cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210217105451-b926d437f341 h1:2/QtM1mL37YmcsT8HaDNHDgTqqFVw+zr8UzMiBVLzYU= +golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210217105451-b926d437f341/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210309074719-68d13333faf2 h1:46ULzRKLh1CwgRq2dC5SlBzEqqNCi8rreOZnNrbqcIY= +golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200630154851-b2d8b0336632/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200706234117-b22de6825cf7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= +google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180808183934-383e8b2c3b9e/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181107211654-5fc9ac540362/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190415143225-d1146b9035b9/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200626011028-ee7919e894b5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200707001353-8e8330bf89df/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201022181438-0ff5f38871d5 h1:YejJbGvoWsTXHab4OKNrzk27Dr7s4lPLnewbHue1+gM= google.golang.org/genproto v0.0.0-20201022181438-0ff5f38871d5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.0/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= @@ -770,7 +1149,11 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/ini.v1 v1.55.0 h1:E8yzL5unfpW3M6fz/eB7Cb5MQAYSZ7GKo4Qth+N2sgQ= @@ -780,10 +1163,12 @@ gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI= gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= @@ -792,6 +1177,13 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/goversion v1.2.0/go.mod h1:Eih9y/uIBS3ulggl7KNJ09xGSLcuNaLgmvvqa07sgfo= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/cmd/dcrdata/main.go b/cmd/dcrdata/main.go index ce6ea7e3a..c7403653f 100644 --- a/cmd/dcrdata/main.go +++ b/cmd/dcrdata/main.go @@ -27,7 +27,7 @@ import ( "github.com/decred/dcrdata/db/dcrpg/v6" "github.com/decred/dcrdata/exchanges/v3" "github.com/decred/dcrdata/gov/v4/agendas" - "github.com/decred/dcrdata/gov/v4/politeia" + politeia "github.com/decred/dcrdata/gov/v4/politeia" "github.com/decred/dcrdata/v6/blockdata" "github.com/decred/dcrdata/v6/db/cache" @@ -45,7 +45,6 @@ import ( mw "github.com/decred/dcrdata/cmd/dcrdata/middleware" notify "github.com/decred/dcrdata/cmd/dcrdata/notification" - "github.com/dmigwi/go-piparser/proposals" "github.com/go-chi/chi/v5" "github.com/google/gops/agent" ) @@ -159,22 +158,6 @@ func _main(ctx context.Context) error { log.Infof("Loaded StakeDatabase at height %d", stakeDBHeight) - var piParser dcrpg.ProposalsFetcher - if !cfg.DisablePiParser { - log.Infof("Setting up the Politeia's proposals clone repository. Please wait...") - // If repoName and repoOwner are set to empty strings the defaults are used. - parser, err := proposals.NewParser(cfg.PiPropRepoOwner, cfg.PiPropRepoName, cfg.DataDir) - if err != nil { - // since this piparser isn't a requirement to run the explorer, its - // failure should not block the system from running. - log.Error(err) - } - - if parser != nil { - piParser = parser - } - } - // Main chain DB var newPGIndexes, updateAllAddresses bool pgHost, pgPort := cfg.PGHost, "" @@ -215,7 +198,7 @@ func _main(ctx context.Context) error { mpChecker := rpcutils.NewMempoolAddressChecker(dcrdClient, activeChain) chainDB, err := dcrpg.NewChainDB(ctx, &dbCfg, - stakeDB, mpChecker, piParser, dcrdClient, requestShutdown) + stakeDB, mpChecker, dcrdClient, requestShutdown) if chainDB != nil { defer chainDB.Close() } @@ -450,21 +433,12 @@ func _main(ctx context.Context) error { return fmt.Errorf("failed to create new agendas db instance: %v", err) } - // Creates a new or loads an existing proposals db instance that helps to - // store and retrieve proposals data. Proposals votes is Off-Chain - // data stored in github repositories away from the decred blockchain. It also - // creates a new http client needed to query Politeia API endpoints. - // When piparser is disabled, disable the API calls too. - var proposalsInstance explorer.PoliteiaBackend - - if !cfg.DisablePiParser { - proposalsInstance, err = politeia.NewProposalsDB(cfg.PoliteiaAPIURL, - filepath.Join(cfg.DataDir, cfg.ProposalsFileName)) - if err != nil { - return fmt.Errorf("failed to create new proposals db instance: %v", err) - } - } else { - log.Info("Piparser is disabled. Proposals API has been disabled too") + // Creates a new or loads an existing proposals db instance that stores and + // retrieves data from politeia and is used by dcrdata. + proposalsDB, err := politeia.NewProposalsDB(cfg.PoliteiaURL, + filepath.Join(cfg.DataDir, cfg.ProposalsFileName)) + if err != nil { + return fmt.Errorf("failed to create new proposals db instance: %v", err) } // A vote tracker tracks current block and stake versions and votes. Only @@ -480,23 +454,22 @@ func _main(ctx context.Context) error { } // Create the explorer system. - explore := explorer.New(&explorer.ExplorerConfig{ - DataSource: chainDB, - ChartSource: charts, - UseRealIP: cfg.UseRealIP, - AppVersion: Version(), - DevPrefetch: !cfg.NoDevPrefetch, - Viewsfolder: "views", - XcBot: xcBot, - AgendasSource: agendaDB, - Tracker: tracker, - ProposalsSource: proposalsInstance, - PoliteiaURL: cfg.PoliteiaAPIURL, - MainnetLink: cfg.MainnetLink, - TestnetLink: cfg.TestnetLink, - ReloadHTML: cfg.ReloadHTML, - OnionAddress: cfg.OnionAddress, + DataSource: chainDB, + ChartSource: charts, + UseRealIP: cfg.UseRealIP, + AppVersion: Version(), + DevPrefetch: !cfg.NoDevPrefetch, + Viewsfolder: "views", + XcBot: xcBot, + AgendasSource: agendaDB, + Tracker: tracker, + Proposals: proposalsDB, + PoliteiaURL: cfg.PoliteiaURL, + MainnetLink: cfg.MainnetLink, + TestnetLink: cfg.TestnetLink, + ReloadHTML: cfg.ReloadHTML, + OnionAddress: cfg.OnionAddress, }) // TODO: allow views config if explore == nil { @@ -643,14 +616,14 @@ func _main(ctx context.Context) error { // Start dcrdata's JSON web API. app := api.NewContext(&api.AppContextConfig{ - Client: dcrdClient, - Params: activeChain, - DataSource: chainDB, - XcBot: xcBot, - AgendasDBInstance: agendaDB, - MaxAddrs: cfg.MaxCSVAddrs, - Charts: charts, - IsPiparserDisabled: cfg.DisablePiParser, + Client: dcrdClient, + Params: activeChain, + DataSource: chainDB, + XcBot: xcBot, + AgendasDBInstance: agendaDB, + ProposalsDB: proposalsDB, + MaxAddrs: cfg.MaxCSVAddrs, + Charts: charts, }) // Start the notification hander for keeping /status up-to-date. wg.Add(1) @@ -759,7 +732,7 @@ func _main(ctx context.Context) error { r.Get("/agendas", explore.AgendasPage) r.With(explorer.AgendaPathCtx).Get("/agenda/{agendaid}", explore.AgendaPage) r.Get("/proposals", explore.ProposalsPage) - r.With(explorer.ProposalPathCtx).Get("/proposal/{proposalrefid}", explore.ProposalPage) + r.With(explorer.ProposalPathCtx).Get("/proposal/{proposaltoken}", explore.ProposalPage) r.Get("/decodetx", explore.DecodeTxPage) r.Get("/search", explore.Search) r.Get("/charts", explore.Charts) @@ -978,32 +951,15 @@ func _main(ctx context.Context) error { return fmt.Errorf("updating agendas db failed: %v", err) } - // Piparser should run updates only after the initial sync - if !cfg.DisablePiParser { - // Initiate the piparser handler here. - chainDB.StartPiparserHandler() - - // Retrieve newly added proposals and add them to the proposals db(storm). - // Proposal db update is made asynchronously to ensure that the system works - // even when the Politeia API endpoint set is down. - go func() { - if err := proposalsInstance.CheckProposalsUpdates(); err != nil { - log.Errorf("updating proposals db failed: %v", err) - } - - log.Info("Updating Politeia proposals...") - - // Fetch updates for Politiea's Proposal history(votes) data via the - // parser. An error in fetching the updates should not stop the - // system since it could be a git issue. - commitsCount, err := chainDB.PiProposalsHistory() - if err != nil { - log.Errorf("chainDB.PiProposalsHistory failed : %v", err) - } else { - log.Infof("%d Politeia git commits were processed", commitsCount) - } - }() - } + // Retrieve updates and newly added proposals from Politeia and store them + // on our stormdb. This call is made asynchronously to not block execution + // while the proposals db is syncing. + log.Info("Syncing proposals data with Politeia...") + go func() { + if err := proposalsDB.ProposalsSync(); err != nil { + log.Errorf("updating proposals db failed: %v", err) + } + }() // Monitors for new blocks, transactions, and reorgs should not run before // blockchain syncing and DB indexing completes. If started before then, the diff --git a/cmd/dcrdata/public/js/controllers/proposal_controller.js b/cmd/dcrdata/public/js/controllers/proposal_controller.js index 949f4df6f..ab0ace3ba 100644 --- a/cmd/dcrdata/public/js/controllers/proposal_controller.js +++ b/cmd/dcrdata/public/js/controllers/proposal_controller.js @@ -5,8 +5,8 @@ import globalEventBus from '../services/event_bus_service' import { getDefault } from '../helpers/module_helper' import { multiColumnBarPlotter, synchronize } from '../helpers/chart_helper' import dompurify from 'dompurify' +import axios from 'axios' import humanize from '../helpers/humanize_helper' -import { requestJSON } from '../helpers/http.js' const common = { labelsKMB: true, @@ -130,7 +130,8 @@ export default class extends Controller { this.approvalMeter = new MiniMeter(this.approvalMeterTarget, opts) } - chartData = await requestJSON('/api/proposal/' + this.tokenTarget.dataset.hash) + const response = await axios.get('/api/proposal/' + this.tokenTarget.dataset.hash) + chartData = response.data Dygraph = await getDefault( import(/* webpackChunkName: "dygraphs" */ '../vendor/dygraphs.min.js') @@ -150,28 +151,43 @@ export default class extends Controller { setChartsData () { let total = 0 let yes = 0 + let hourlyYes = 0 + let hourlyNo = 0 + let currentDate = new Date(chartData?.time[0] * 1000) + let currentHour = currentDate.getHours() percentData = [] cumulativeData = [] hourlyVotesData = [] chartData.time.map((n, i) => { - const formatedDate = new Date(n) + const formatedDate = new Date(n * 1000) yes += chartData.yes[i] total += (chartData.no[i] + chartData.yes[i]) const percent = ((yes * 100) / total).toFixed(2) - percentData.push([formatedDate, parseFloat(percent)]) - cumulativeData.push([formatedDate, total]) - hourlyVotesData.push([formatedDate, chartData.yes[i], chartData.no[i] * -1]) + // accumulate hourly vote data. currentDate keeps track + // of the hour of such date we are parsing data for + hourlyYes += chartData.yes[i] + hourlyNo += chartData.no[i] + if (formatedDate.getHours() !== currentHour) { + currentDate.setMinutes(0) + percentData.push([currentDate, parseFloat(percent)]) + cumulativeData.push([currentDate, total]) + hourlyVotesData.push([currentDate, hourlyYes, hourlyNo * -1]) + currentDate = formatedDate + currentHour = formatedDate.getHours() + hourlyYes = 0 + hourlyNo = 0 + } }) // add empty data at the beginning and end of hourlyVotesData // to pad the bar chart data on both ends - const firstDate = new Date(chartData.time[0]) + const firstDate = new Date(chartData.time[0] * 1000) firstDate.setHours(firstDate.getHours() - 1) - const lastDate = new Date(chartData.time[chartData.time.length - 1]) + const lastDate = new Date(chartData.time[chartData.time.length - 1] * 1000) lastDate.setHours(lastDate.getHours() + 1) hourlyVotesData.unshift([firstDate, 0, 0]) hourlyVotesData.push([lastDate, 0, 0]) diff --git a/cmd/dcrdata/views/proposal.tmpl b/cmd/dcrdata/views/proposal.tmpl index 8408551cc..8a6cf59eb 100644 --- a/cmd/dcrdata/views/proposal.tmpl +++ b/cmd/dcrdata/views/proposal.tmpl @@ -8,35 +8,35 @@
- {{$status := .VoteStatus.ShortDesc}} + {{$status := $metadata.VoteStatusDesc}} {{- /* INVALID AND NON-EXISTENT */ -}} - {{if or (eq $status "Invalid") (eq $status "Doesn't Exist")}} - {{if .AbandonedDate}} + {{if eq $status "invalid"}} + {{if .AbandonedAt}} {{block "abandoned" .}}
{{.Name}}
Proposal abandoned
-
This proposal was designated abandoned {{TimeConversion .AbandonedDate}}.
+
This proposal was designated abandoned {{TimeConversion .AbandonedAt}}.
{{end}} {{else}} Invalid proposal: {{.Name}} {{end}} {{- /* NOT AUTHORIZED */ -}} - {{else if eq $status "Not Authorized"}} - {{if .AbandonedDate}} + {{else if eq $status "unauthorized"}} + {{if .AbandonedAt}} {{template "abandoned" .}} {{else}}
{{.Name}}
Proposal in discussion
{{.Username}} has not initiated voting yet. There is - an ongoing discussion + an ongoing discussion of this proposal happening on Politeia.
{{end}} {{- /* AUTHORIZED */ -}} - {{else if eq $status "Authorized"}} + {{else if eq $status "authorized"}}
{{.Name}}
Vote scheduled
@@ -45,9 +45,9 @@
{{- /* LIVE OR FINISHED */ -}} - {{else if or (eq $status "Started") (eq $status "Finished")}} + {{else if or (eq $status "started") (eq $status "finished") (eq $status "approved") (eq $status "rejected")}}
{{.Name}}
- {{if eq $status "Started"}} + {{if eq $status "started"}}
Voting now
@@ -80,13 +80,13 @@
{{printf "%.1f" (f32x100 $metadata.Approval)}}% - approval of {{intComma $metadata.VoteCount}} votes ({{printf "%.0f" (percentage $metadata.VoteCount .NumOfEligibleVotes)}}% turnout) + approval of {{intComma $metadata.VoteCount}} votes ({{printf "%.0f" (percentage $metadata.VoteCount (int64 .EligibleTickets))}}% turnout) {{if $metadata.QuorumAchieved}}
Quorum achieved
{{else}} - {{if eq $status "Started"}} + {{if eq $status "started"}} Quorum
{{$metadata.VoteCount}} of {{$metadata.QuorumCount}} needed votes @@ -100,7 +100,7 @@
{{end}}{{/* END LIVE OR FINISHED */ -}}
- + Discussion @@ -119,33 +119,39 @@ Author: {{.Username}} Status: - {{.State.String}} / {{.Status.String}} + + {{$metadata.ProposalStateDesc}} / {{$metadata.ProposalStatusDesc}} + {{if $metadata.VoteCount}} Yes: - {{$metadata.Yes}} votes ({{printf "%.1f" (f32x100 $metadata.Approval)}}%) + + {{$metadata.Yes}} votes ({{printf "%.1f" (f32x100 $metadata.Approval)}}%) + No: - {{$metadata.No}} votes ({{printf "%.1f" (f32x100 $metadata.Rejection)}}%) + + {{$metadata.No}} votes ({{printf "%.1f" (f32x100 $metadata.Rejection)}}%) + Eligible: - {{.NumOfEligibleVotes}} tickets + {{.EligibleTickets}} tickets Voting Period: {{$metadata.StartHeight}} + >{{.StartBlockHeight}} – - {{if eq $status "Finished"}} - {{.Endheight}} + {{if eq $status "finished"}} + {{.EndBlockHeight}} {{else}} - {{.Endheight}} + {{.EndBlockHeight}} {{end}} {{end}} Discussion: - {{.NumComments}} comments + {{.CommentsCount}} comments Updated: {{TimeConversion .Timestamp}} @@ -153,11 +159,11 @@ Version: v{{.Version}} Published: - {{TimeConversion .PublishedDate}} + {{TimeConversion .PublishedAt}} Token: - {{.TokenVal}} + {{.Token}} @@ -169,7 +175,7 @@ {{if gt (len .VoteResults) 1}}
diff --git a/cmd/dcrdata/views/proposals.tmpl b/cmd/dcrdata/views/proposals.tmpl index 9950932c6..910788f92 100644 --- a/cmd/dcrdata/views/proposals.tmpl +++ b/cmd/dcrdata/views/proposals.tmpl @@ -12,9 +12,6 @@  (Proposals Sync:   ago - Votes Sync:  -  ago - )
@@ -137,15 +134,15 @@ {{range $i, $v := .Proposals}} {{with $v}} - {{$votesTotalPercent := percentage $v.TotalVotes $v.NumOfEligibleVotes}} + {{$votesTotalPercent := percentage (int64 $v.TotalVotes) (int64 $v.EligibleTickets)}} - {{.Name}} + {{.Name}}  ({{.Username}}) {{if .VoteStatus}} - {{if eq .VoteStatus.ShortDesc "Not Authorized"}} - {{if .AbandonedDate}} + {{if eq (index $.VotesStatus .VoteStatus) "Unauthorized"}} + {{if .AbandonedAt}} Abandoned @@ -160,9 +157,9 @@ {{else}} {{range $i, $vr := .VoteResults}} - {{if eq $vr.Option.OptionID "yes"}} - {{$votesPercent := percentage $vr.VotesReceived $v.TotalVotes}} - {{$blocksRemaining := subtract (int64 (toInt $v.Endheight)) (int64 $.Tip.Height)}} + {{if eq $vr.ID "yes"}} + {{$votesPercent := percentage (int64 $vr.Votes) (int64 $v.TotalVotes)}} + {{$blocksRemaining := subtract (int64 $v.EndBlockHeight) (int64 $.Tip.Height)}} {{if gt $blocksRemaining 0}} In Progress @@ -207,11 +204,11 @@ {{end}} - {{if and .VoteStatus (ne .VoteStatus.ShortDesc "Not Authorized")}} + {{if and .VoteStatus (ne (index $.VotesStatus .VoteStatus) "Unauthorized")}} {{.TotalVotes}} ( - {{- if eq $v.NumOfEligibleVotes 0 -}} + {{- if eq $v.EligibleTickets 0 -}} 0% {{else -}} {{printf "%.0f" $votesTotalPercent}}% @@ -222,7 +219,7 @@ — {{end}} - + {{end}} {{end}} diff --git a/db/dbtypes/types.go b/db/dbtypes/types.go index 97adc96a6..49396ca9d 100644 --- a/db/dbtypes/types.go +++ b/db/dbtypes/types.go @@ -1680,13 +1680,6 @@ type ChartsData struct { NetHash []uint64 `json:"nethash,omitempty"` } -// ProposalChartsData defines the data used to plot proposal votes charts. -type ProposalChartsData struct { - Yes []uint64 `json:"yes,omitempty"` - No []uint64 `json:"no,omitempty"` - Time []TimeDef `json:"time,omitempty"` -} - // ScriptPubKeyData is part of the result of decodescript(ScriptPubKeyHex) type ScriptPubKeyData struct { ReqSigs uint32 `json:"reqSigs"` diff --git a/db/dcrpg/chkdcrpg/main.go b/db/dcrpg/chkdcrpg/main.go index eb96fbd51..fe8b9468a 100644 --- a/db/dcrpg/chkdcrpg/main.go +++ b/db/dcrpg/chkdcrpg/main.go @@ -136,8 +136,7 @@ func mainCore(ctx context.Context) error { // Construct a ChainDB without a stakeDB to allow quick dropping of tables. mpChecker := rpcutils.NewMempoolAddressChecker(client, activeChain) - var piParser dcrpg.ProposalsFetcher - db, err := dcrpg.NewChainDB(ctx, &dbCfg, nil, mpChecker, piParser, client, func() {}) + db, err := dcrpg.NewChainDB(ctx, &dbCfg, nil, mpChecker, client, func() {}) if db != nil { defer db.Close() } diff --git a/db/dcrpg/go.mod b/db/dcrpg/go.mod index c04db56e9..b3f776f43 100644 --- a/db/dcrpg/go.mod +++ b/db/dcrpg/go.mod @@ -18,7 +18,6 @@ require ( github.com/decred/dcrd/wire v1.4.0 github.com/decred/dcrdata/v6 v6.0.0 github.com/decred/slog v1.1.0 - github.com/dmigwi/go-piparser/proposals v0.0.0-20191219171828-ae8cbf4067e1 github.com/dustin/go-humanize v1.0.0 github.com/jessevdk/go-flags v1.4.1-0.20200711081900-c17162fe8fd7 github.com/jrick/logrotate v1.0.0 diff --git a/db/dcrpg/go.sum b/db/dcrpg/go.sum index 215ff8563..141965815 100644 --- a/db/dcrpg/go.sum +++ b/db/dcrpg/go.sum @@ -78,8 +78,6 @@ github.com/dgraph-io/ristretto v0.0.2 h1:a5WaUrDa0qm0YrAAS1tUykT5El3kt62KNZZeMxQ github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dmigwi/go-piparser/proposals v0.0.0-20191219171828-ae8cbf4067e1 h1:8+y5flqx5OCcYOuzKGnUS1PluG9hexfL5I3IAN4aym4= -github.com/dmigwi/go-piparser/proposals v0.0.0-20191219171828-ae8cbf4067e1/go.mod h1:bVFHMc7PF69eSpDREy2MnoZYr8YMQjGDEUJudtQUEis= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= diff --git a/db/dcrpg/indexing.go b/db/dcrpg/indexing.go index e02dabd19..3b1d93ea9 100644 --- a/db/dcrpg/indexing.go +++ b/db/dcrpg/indexing.go @@ -330,30 +330,6 @@ func DeindexAgendaVotesTableOnAgendaID(db *sql.DB) (err error) { return } -// proposals table indexes - -func IndexProposalsTableOnToken(db *sql.DB) (err error) { - _, err = db.Exec(internal.IndexProposalsTableOnToken) - return -} - -func DeindexProposalsTableOnToken(db *sql.DB) (err error) { - _, err = db.Exec(internal.DeindexProposalsTableOnToken) - return -} - -// proposal votes table indexes - -func IndexProposalVotesTableOnProposalsID(db *sql.DB) (err error) { - _, err = db.Exec(internal.IndexProposalVotesTableOnProposalsID) - return -} - -func DeindexProposalVotesTableOnProposalsID(db *sql.DB) (err error) { - _, err = db.Exec(internal.DeindexProposalVotesTableOnProposalsID) - return -} - // IndexTreasuryTableOnTxHash creates the index for the treasury table over // tx_hash. func IndexTreasuryTableOnTxHash(db *sql.DB) (err error) { @@ -527,12 +503,6 @@ func (pgb *ChainDB) DeindexAll() error { // agenda votes table {DeindexAgendaVotesTableOnAgendaID}, - // proposals table - {DeindexProposalsTableOnToken}, - - // proposal votes table - {DeindexProposalVotesTableOnProposalsID}, - // stats table {DeindexStatsTableOnHeight}, @@ -608,12 +578,6 @@ func (pgb *ChainDB) IndexAll(barLoad chan *dbtypes.ProgressBarLoad) error { {Msg: "addresses table on vout DB ID", IndexFunc: IndexAddressTableOnVoutID}, //{Msg: "addresses table on matching tx hash", IndexFunc: IndexAddressTableOnMatchingTxHash}, - // proposals table - {Msg: "proposals table on Token+Time", IndexFunc: IndexProposalsTableOnToken}, - - // Proposals votes table - {Msg: "Proposals votes table on Proposals ID", IndexFunc: IndexProposalVotesTableOnProposalsID}, - // stats table {Msg: "stats table on height", IndexFunc: IndexStatsTableOnHeight}, diff --git a/db/dcrpg/internal/indexes.go b/db/dcrpg/internal/indexes.go index 4fb6fbd06..e5d54003d 100644 --- a/db/dcrpg/internal/indexes.go +++ b/db/dcrpg/internal/indexes.go @@ -59,14 +59,6 @@ const ( IndexOfAgendaVotesTableOnRowIDs = "uix_agenda_votes" - // proposals table - - IndexOfProposalsTableOnToken = "uix_proposals" - - // proposal votes table - - IndexOfProposalVotesTableOnProposalsID = "uix_proposal_votes" - // stats table IndexOfHeightOnStatsTable = "uix_stats_height" @@ -84,35 +76,33 @@ var AddressesIndexNames = []string{IndexOfAddressTableOnAddress, // IndexDescriptions relate table index names to descriptions of the indexes. var IndexDescriptions = map[string]string{ - IndexOfBlocksTableOnHash: "blocks on hash", - IndexOfBlocksTableOnHeight: "blocks on height", - IndexOfTransactionsTableOnHashes: "transactions on block hash and transaction hash", - IndexOfTransactionsTableOnBlockInd: "transactions on block hash, block index, and tx tree", - IndexOfTransactionsTableOnBlockHeight: "transactions on block height", - IndexOfVinsTableOnVin: "vins on transaction hash and index", - IndexOfVinsTableOnPrevOut: "vins on previous outpoint", - IndexOfVoutsTableOnTxHashInd: "vouts on transaction hash and index", - IndexOfVoutsTableOnSpendTxID: "vouts on spend_tx_row_id", - IndexOfAddressTableOnAddress: "addresses table on address", // TODO: remove if it is redundant with IndexOfAddressTableOnVoutID - IndexOfAddressTableOnVoutID: "addresses table on vout row id, address, and is_funding", - IndexOfAddressTableOnBlockTime: "addresses table on block time", - IndexOfAddressTableOnTx: "addresses table on transaction hash", - IndexOfAddressTableOnMatchingTx: "addresses table on matching tx hash", - IndexOfTicketsTableOnHashes: "tickets table on block hash and transaction hash", - IndexOfTicketsTableOnTxRowID: "tickets table on transactions table row ID", - IndexOfTicketsTableOnPoolStatus: "tickets table on pool status", - IndexOfVotesTableOnHashes: "votes table on block hash and transaction hash", - IndexOfVotesTableOnBlockHash: "votes table on block hash", - IndexOfVotesTableOnCandBlock: "votes table on candidate block", - IndexOfVotesTableOnVersion: "votes table on vote version", - IndexOfVotesTableOnHeight: "votes table on height", - IndexOfVotesTableOnBlockTime: "votes table on block time", - IndexOfMissesTableOnHashes: "misses on ticket hash and block hash", - IndexOfAgendasTableOnName: "agendas on agenda name", - IndexOfAgendaVotesTableOnRowIDs: "agenda_votes on votes table row ID and agendas table row ID", - IndexOfProposalsTableOnToken: "proposals on token and time", - IndexOfProposalVotesTableOnProposalsID: "proposal_votes on proposals row ID", - IndexOfHeightOnStatsTable: "stats table on height", - IndexOfTreasuryTableOnTxHash: "treasury table on tx hash", - IndexOfTreasuryTableOnHeight: "treasury table on block height", + IndexOfBlocksTableOnHash: "blocks on hash", + IndexOfBlocksTableOnHeight: "blocks on height", + IndexOfTransactionsTableOnHashes: "transactions on block hash and transaction hash", + IndexOfTransactionsTableOnBlockInd: "transactions on block hash, block index, and tx tree", + IndexOfTransactionsTableOnBlockHeight: "transactions on block height", + IndexOfVinsTableOnVin: "vins on transaction hash and index", + IndexOfVinsTableOnPrevOut: "vins on previous outpoint", + IndexOfVoutsTableOnTxHashInd: "vouts on transaction hash and index", + IndexOfVoutsTableOnSpendTxID: "vouts on spend_tx_row_id", + IndexOfAddressTableOnAddress: "addresses table on address", // TODO: remove if it is redundant with IndexOfAddressTableOnVoutID + IndexOfAddressTableOnVoutID: "addresses table on vout row id, address, and is_funding", + IndexOfAddressTableOnBlockTime: "addresses table on block time", + IndexOfAddressTableOnTx: "addresses table on transaction hash", + IndexOfAddressTableOnMatchingTx: "addresses table on matching tx hash", + IndexOfTicketsTableOnHashes: "tickets table on block hash and transaction hash", + IndexOfTicketsTableOnTxRowID: "tickets table on transactions table row ID", + IndexOfTicketsTableOnPoolStatus: "tickets table on pool status", + IndexOfVotesTableOnHashes: "votes table on block hash and transaction hash", + IndexOfVotesTableOnBlockHash: "votes table on block hash", + IndexOfVotesTableOnCandBlock: "votes table on candidate block", + IndexOfVotesTableOnVersion: "votes table on vote version", + IndexOfVotesTableOnHeight: "votes table on height", + IndexOfVotesTableOnBlockTime: "votes table on block time", + IndexOfMissesTableOnHashes: "misses on ticket hash and block hash", + IndexOfAgendasTableOnName: "agendas on agenda name", + IndexOfAgendaVotesTableOnRowIDs: "agenda_votes on votes table row ID and agendas table row ID", + IndexOfHeightOnStatsTable: "stats table on height", + IndexOfTreasuryTableOnTxHash: "treasury table on tx hash", + IndexOfTreasuryTableOnHeight: "treasury table on block height", } diff --git a/db/dcrpg/internal/stakestmts.go b/db/dcrpg/internal/stakestmts.go index 98b781d08..d2dcca64c 100644 --- a/db/dcrpg/internal/stakestmts.go +++ b/db/dcrpg/internal/stakestmts.go @@ -1,7 +1,7 @@ package internal // These queries relate primarily to the stake tables ("tickets", "votes", -// "misses", "proposals", "proposal_votes", "agendas", and "agenda_votes"). +// "misses", "agendas", and "agenda_votes"). const ( // tickets table @@ -457,74 +457,6 @@ const ( WHERE agenda_votes.agendas_row_id = (SELECT id from agendas WHERE name = $4) AND votes.height >= $5 AND votes.height <= $6 AND votes.is_mainchain = TRUE ` - - // Proposals Table - - CreateProposalsTable = `CREATE TABLE IF NOT EXISTS proposals ( - id SERIAL PRIMARY KEY, - token TEXT NOT NULL, - author TEXT, - commit_sha TEXT NOT NULL, - time TIMESTAMPTZ - );` - - // Insert - - insertProposalsRow = `INSERT INTO proposals (token, author, commit_sha, time) - VALUES ($1, $2, $3, $4) ` - - InsertProposalsRow = insertProposalsRow + `RETURNING id;` - - UpsertProposalsRow = insertProposalsRow + `ON CONFLICT (token, time) - DO UPDATE SET commit_sha = $3, time = $4 RETURNING id;` - - // Index - - IndexProposalsTableOnToken = `CREATE UNIQUE INDEX ` + IndexOfProposalsTableOnToken + - ` ON proposals(token, time);` - - DeindexProposalsTableOnToken = `DROP INDEX ` + IndexOfProposalsTableOnToken + ` CASCADE;` - - // Select - - SelectProposalsLastCommitTime = `Select time - FROM proposals - ORDER BY time DESC - LIMIT 1;` - - // Proposal Votes table - - CreateProposalVotesTable = `CREATE TABLE IF NOT EXISTS proposal_votes ( - id SERIAL PRIMARY KEY, - proposals_row_id INT8, - ticket TEXT NOT NULL, - choice TEXT NOT NULL - );` - - // Insert - - insertProposalVotesRow = `INSERT INTO proposal_votes (proposals_row_id, ticket, choice) - VALUES ($1, $2, $3) ` - - InsertProposalVotesRow = insertProposalVotesRow + `RETURNING id;` - - // Index - - IndexProposalVotesTableOnProposalsID = `CREATE INDEX ` + IndexOfProposalVotesTableOnProposalsID + - ` ON proposal_votes(proposals_row_id);` - - DeindexProposalVotesTableOnProposalsID = `DROP INDEX ` + IndexOfProposalVotesTableOnProposalsID + ` CASCADE;` - - // Select - - SelectProposalVotesChartData = `SELECT proposals.time, - COUNT(CASE WHEN proposal_votes.choice = 'No' THEN 1 ElSE NULL END) as no, - COUNT(CASE WHEN proposal_votes.choice = 'Yes' THEN 1 ElSE NULL END) as yes - FROM proposal_votes - INNER JOIN proposals on proposals.id = proposal_votes.proposals_row_id - WHERE proposals.token = $1 - GROUP BY proposals.time - ORDER BY proposals.time;` ) // MakeTicketInsertStatement returns the appropriate tickets insert statement @@ -592,16 +524,6 @@ func MakeAgendaVotesInsertStatement(checked bool) string { return InsertAgendaVotesRow } -// MakeProposalsInsertStatement returns the appropriate proposals insert statement for -// the desired conflict checking and handling behavior. See the description of -// MakeTicketInsertStatement for details. -func MakeProposalsInsertStatement(checked bool) string { - if checked { - return UpsertProposalsRow - } - return InsertProposalsRow -} - // MakeSelectTicketsByPurchaseDate returns the selectTicketsByPurchaseDate query func MakeSelectTicketsByPurchaseDate(group string) string { return formatGroupingQuery(selectTicketsByPurchaseDate, group, "transactions.block_time") diff --git a/db/dcrpg/pgblockchain.go b/db/dcrpg/pgblockchain.go index e82cf2e21..e474f8ca6 100644 --- a/db/dcrpg/pgblockchain.go +++ b/db/dcrpg/pgblockchain.go @@ -15,7 +15,6 @@ import ( "sort" "strings" "sync" - "sync/atomic" "time" "decred.org/dcrwallet/wallet/txrules" @@ -27,7 +26,6 @@ import ( chainjson "github.com/decred/dcrd/rpc/jsonrpc/types/v2" "github.com/decred/dcrd/rpcclient/v6" "github.com/decred/dcrd/wire" - pitypes "github.com/dmigwi/go-piparser/proposals/types" humanize "github.com/dustin/go-humanize" "github.com/lib/pq" @@ -69,13 +67,6 @@ func IsRetryError(err error) bool { // agenda_votes table. var storedAgendas map[string]dbtypes.MileStone -// isPiparserRunning is the flag set when a Piparser instance is running. -const isPiparserRunning = uint32(1) - -// piParserCounter is a counter that helps guarantee that only one instance -// of proposalsUpdateHandler can ever be running at any one given moment. -var piParserCounter uint32 - // ticketPoolDataCache stores the most recent ticketpool graphs information // fetched to minimize the possibility of making multiple queries to the db // fetching the same information. @@ -88,13 +79,6 @@ type ticketPoolDataCache struct { DonutGraphCache map[dbtypes.TimeBasedGrouping]*dbtypes.PoolTicketsData } -// ProposalsFetcher defines the interface of the proposals plug-n-play data source. -type ProposalsFetcher interface { - UpdateSignal() <-chan struct{} - ProposalsHistory() ([]*pitypes.History, error) - ProposalsHistorySince(since time.Time) ([]*pitypes.History, error) -} - // ticketPoolGraphsCache persists the latest ticketpool data queried from the db. var ticketPoolGraphsCache = &ticketPoolDataCache{ Height: make(map[dbtypes.TimeBasedGrouping]int64), @@ -274,9 +258,6 @@ type ChainDB struct { mixSetDiffsMtx sync.Mutex mixSetDiffs map[uint32]int64 // height to value diff deployments *ChainDeployments - piparser ProposalsFetcher - proposalsSync lastSync - piUpdateRunning uint32 cockroach bool MPC *mempool.MempoolDataCache // BlockCache stores apitypes.BlockDataBasic and apitypes.StakeInfoExtended @@ -311,12 +292,6 @@ type BestBlock struct { hash string } -// lastSync defines the latest sync time for the proposal votes sync. -type lastSync struct { - mtx sync.RWMutex - syncTime time.Time -} - func (pgb *ChainDB) timeoutError() string { return fmt.Sprintf("%s after %v", dbtypes.TimeoutPrefix, pgb.queryTimeout) } @@ -484,8 +459,7 @@ type ChainDBCfg struct { // and Decred network parameters. By default, duplicate row checks on insertion // are enabled. See EnableDuplicateCheckOnInsert to change this behavior. func NewChainDB(ctx context.Context, cfg *ChainDBCfg, stakeDB *stakedb.StakeDatabase, - mp rpcutils.MempoolAddressChecker, parser ProposalsFetcher, client *rpcclient.Client, - shutdown func()) (*ChainDB, error) { + mp rpcutils.MempoolAddressChecker, client *rpcclient.Client, shutdown func()) (*ChainDB, error) { // Connect to the PostgreSQL daemon and return the *sql.DB. dbi := cfg.DBi db, err := Connect(dbi.Host, dbi.Port, dbi.User, dbi.Pass, dbi.DBName) @@ -759,7 +733,6 @@ func NewChainDB(ctx context.Context, cfg *ChainDBCfg, stakeDB *stakedb.StakeData utxoCache: newUtxoStore(5e4), mixSetDiffs: make(map[uint32]int64), deployments: new(ChainDeployments), - piparser: parser, cockroach: cockroach, MPC: new(mempool.MempoolDataCache), BlockCache: apitypes.NewAPICache(1e4), @@ -781,19 +754,6 @@ func NewChainDB(ctx context.Context, cfg *ChainDBCfg, stakeDB *stakedb.StakeData return chainDB, nil } -// StartPiparserHandler controls how piparser update handler will be initiated. -// This handler should to be run once only when the first sync after startup completes. -func (pgb *ChainDB) StartPiparserHandler() { - if atomic.CompareAndSwapUint32(&piParserCounter, 0, isPiparserRunning) { - // Start the proposal updates handler async method. - pgb.proposalsUpdateHandler() - - log.Info("Piparser instance to handle updates is now active") - } else { - log.Error("piparser instance is already running, another one cannot be activated") - } -} - // Close closes the underlying sql.DB connection to the database. func (pgb *ChainDB) Close() error { return pgb.db.Close() @@ -850,7 +810,7 @@ var ( // that the legacy table versioning system is in use. func versionCheck(db *sql.DB) (*DatabaseVersion, CompatAction, error) { // Detect an empty database, only checking for the "blocks" table since some - // of the tables are created by schema upgrades (e.g. proposal_votes). + // of the tables are created by schema upgrades. exists, err := TableExists(db, "blocks") if err != nil { return nil, Unknown, err @@ -1198,128 +1158,14 @@ func (pgb *ChainDB) VotesInBlock(hash string) (int16, error) { return voters, nil } -// proposalsUpdateHandler runs in the background asynchronous to retrieve the -// politeia proposal updates that the piparser tool signaled. -func (pgb *ChainDB) proposalsUpdateHandler() { - // Do not initiate the async update if invalid or disabled piparser instance was found. - if pgb.piparser == nil { - log.Error("invalid or disabled piparser instance found: proposals async update stopped") - return - } - - go func() { - defer func() { - if r := recover(); r != nil { - log.Errorf("recovered from piparser panic in proposalsUpdateHandler: %v", r) - select { - case <-time.NewTimer(time.Minute).C: - log.Infof("attempting to restart proposalsUpdateHandler") - pgb.proposalsUpdateHandler() - case <-pgb.ctx.Done(): - } - } - }() - for range pgb.piparser.UpdateSignal() { - count, err := pgb.PiProposalsHistory() - if err != nil { - log.Errorf("pgb.PiProposalsHistory failed: %v", err) - } else { - log.Infof("%d politeia's proposal commits were processed", count) - } - } - }() -} - -// LastPiParserSync returns last time value when the piparser run sync on proposals -// and proposal_votes table. -func (pgb *ChainDB) LastPiParserSync() time.Time { - pgb.proposalsSync.mtx.RLock() - defer pgb.proposalsSync.mtx.RUnlock() - return pgb.proposalsSync.syncTime -} - -// PiProposalsHistory queries the politeia's proposal updates via the parser tool -// and pushes them to the proposals and proposal_votes tables. -func (pgb *ChainDB) PiProposalsHistory() (int64, error) { - if pgb.piparser == nil { - return -1, fmt.Errorf("invalid piparser instance was found") - } - if !atomic.CompareAndSwapUint32(&pgb.piUpdateRunning, 0, 1) { - return -1, fmt.Errorf("Pi repo parser updates already processing") - } - defer atomic.StoreUint32(&pgb.piUpdateRunning, 0) - - pgb.proposalsSync.mtx.Lock() - pgb.proposalsSync.syncTime = time.Now().UTC() - pgb.proposalsSync.mtx.Unlock() - - var isChecked bool - var proposalsData []*pitypes.History - - lastUpdate, err := retrieveLastCommitTime(pgb.db) - switch { - case errors.Is(err, sql.ErrNoRows): - log.Infof("Retrieving entire proposal history...") - // No records exists yet fetch all the history. - proposalsData, err = pgb.piparser.ProposalsHistory() - - case err != nil: - return -1, fmt.Errorf("retrieveLastCommitTime failed: %w", err) - - default: - log.Infof("Retrieving proposal history since %v...", lastUpdate) - // Fetch the updates since the last insert only. - proposalsData, err = pgb.piparser.ProposalsHistorySince(lastUpdate) - isChecked = true - } - - if err != nil { - return -1, fmt.Errorf("politeia proposals fetch failed: %w", err) - } - - var commitsCount int64 - - log.Infof("Storing %d new proposal data records...", len(proposalsData)) - for _, entry := range proposalsData { - if entry.CommitSHA == "" { - // If missing commit sha ignore the entry. - continue - } - - // Multiple tokens votes data can be packed in a single Politeia's commit. - for _, val := range entry.Patch { - if val.Token == "" { - // If missing token ignore it. - continue - } - - id, err := InsertProposal(pgb.db, val.Token, entry.Author, - entry.CommitSHA, entry.Date, isChecked) - if err != nil { - return -1, fmt.Errorf("InsertProposal failed: %w", err) - } - - for _, vote := range val.VotesInfo { - _, err = InsertProposalVote(pgb.db, id, vote.Ticket, - string(vote.VoteBit), isChecked) - if err != nil { - return -1, fmt.Errorf("InsertProposalVote failed: %w", err) - } - } - } - commitsCount++ - } - - return commitsCount, err -} - // ProposalVotes retrieves all the votes data associated with the provided token. -func (pgb *ChainDB) ProposalVotes(proposalToken string) (*dbtypes.ProposalChartsData, error) { - ctx, cancel := context.WithTimeout(pgb.ctx, pgb.queryTimeout) - defer cancel() - chartsData, err := retrieveProposalVotesData(ctx, pgb.db, proposalToken) - return chartsData, pgb.replaceCancelError(err) -} +// TODO: Rewriting this func. may not be in chaindb struct, and in appContext instead +// func (pgb *ChainDB) ProposalVotes(proposalToken string) (*dbtypes.ProposalChartsData, error) { +// ctx, cancel := context.WithTimeout(pgb.ctx, pgb.queryTimeout) +// defer cancel() +// chartsData, err := retrieveProposalVotesData(ctx, pgb.db, proposalToken) +// return chartsData, pgb.replaceCancelError(err) +// } // SpendingTransactions retrieves all transactions spending outpoints from the // specified funding transaction. The spending transaction hashes, the spending diff --git a/db/dcrpg/pgblockchain_common_test.go b/db/dcrpg/pgblockchain_common_test.go index b13251fad..cb1dcd36d 100644 --- a/db/dcrpg/pgblockchain_common_test.go +++ b/db/dcrpg/pgblockchain_common_test.go @@ -9,13 +9,11 @@ import ( "os" "runtime" "testing" - "time" "github.com/decred/dcrd/chaincfg/v3" "github.com/decred/dcrdata/v6/db/cache" "github.com/decred/dcrdata/v6/testutil/dbconfig" "github.com/decred/slog" - pitypes "github.com/dmigwi/go-piparser/proposals/types" ) type MemStats runtime.MemStats @@ -57,14 +55,6 @@ func (p *dummyParser) UpdateSignal() <-chan struct{} { return make(chan struct{}) } -func (p *dummyParser) ProposalsHistory() ([]*pitypes.History, error) { - return []*pitypes.History{}, nil -} - -func (p *dummyParser) ProposalsHistorySince(since time.Time) ([]*pitypes.History, error) { - return []*pitypes.History{}, nil -} - func openDB() (func() error, error) { dbi := &DBInfo{ Host: dbconfig.PGTestsHost, diff --git a/db/dcrpg/queries.go b/db/dcrpg/queries.go index 7754aa0c1..d462291fd 100644 --- a/db/dcrpg/queries.go +++ b/db/dcrpg/queries.go @@ -3876,61 +3876,6 @@ func retrieveTicketByOutputCount(ctx context.Context, db *sql.DB, interval int64 return heightArr, soloArr, pooledArr, err } -// --- Proposals and Proposal_votes tables --- - -// InsertProposal adds the proposal details per commit to the proposal table. -func InsertProposal(db *sql.DB, tokenHash, author, commit string, - timestamp time.Time, checked bool) (uint64, error) { - insertStatement := internal.MakeProposalsInsertStatement(checked) - var id uint64 - err := db.QueryRow(insertStatement, tokenHash, author, commit, timestamp).Scan(&id) - return id, err -} - -// InsertProposalVote add the proposal votes entries to the proposal_votes table. -func InsertProposalVote(db *sql.DB, proposalRowID uint64, ticket, choice string, - checked bool) (uint64, error) { - var id uint64 - err := db.QueryRow(internal.InsertProposalVotesRow, proposalRowID, ticket, choice).Scan(&id) - return id, err -} - -// retrieveLastCommitTime returns the last commit timestamp whole proposal votes -// data was fetched and updated in both proposals and proposal_votes table. -func retrieveLastCommitTime(db *sql.DB) (timestamp time.Time, err error) { - err = db.QueryRow(internal.SelectProposalsLastCommitTime).Scan(×tamp) - return -} - -// retrieveProposalVotesData returns the vote data associated with the provided -// proposal token. -func retrieveProposalVotesData(ctx context.Context, db *sql.DB, - proposalToken string) (*dbtypes.ProposalChartsData, error) { - rows, err := db.QueryContext(ctx, internal.SelectProposalVotesChartData, proposalToken) - if err != nil { - return nil, err - } - - defer closeRows(rows) - - data := new(dbtypes.ProposalChartsData) - for rows.Next() { - var yes, no uint64 - var timestamp time.Time - - if err = rows.Scan(×tamp, &no, &yes); err != nil { - return nil, err - } - - data.No = append(data.No, no) - data.Yes = append(data.Yes, yes) - data.Time = append(data.Time, dbtypes.NewTimeDef(timestamp)) - } - err = rows.Err() - - return data, err -} - // --- blocks and block_chain tables --- // InsertBlock inserts the specified dbtypes.Block as with the given diff --git a/db/dcrpg/tables.go b/db/dcrpg/tables.go index ce69b1b6e..ac77a43e2 100644 --- a/db/dcrpg/tables.go +++ b/db/dcrpg/tables.go @@ -26,8 +26,6 @@ var createTableStatements = [][2]string{ {"agendas", internal.CreateAgendasTable}, {"agenda_votes", internal.CreateAgendaVotesTable}, {"testing", internal.CreateTestingTable}, - {"proposals", internal.CreateProposalsTable}, - {"proposal_votes", internal.CreateProposalVotesTable}, {"stats", internal.CreateStatsTable}, {"treasury", internal.CreateTreasuryTable}, {"swaps", internal.CreateAtomicSwapTable}, diff --git a/gov/go.mod b/gov/go.mod index 413c71cd2..4a197c4a3 100644 --- a/gov/go.mod +++ b/gov/go.mod @@ -9,7 +9,7 @@ require ( github.com/decred/dcrd/chaincfg/v3 v3.0.0 github.com/decred/dcrd/dcrjson/v3 v3.1.0 github.com/decred/dcrd/rpc/jsonrpc/types/v2 v2.3.0 - github.com/decred/dcrdata/v6 v6.0.0 - github.com/decred/politeia v0.0.0-20191031182202-b33af07598f2 + github.com/decred/dcrdata/v6 v6.0.0-20210510222533-6a2ca18d4382 + github.com/decred/politeia v1.0.1 github.com/decred/slog v1.1.0 ) diff --git a/gov/go.sum b/gov/go.sum index 9d7f1c36f..6205cb5ff 100644 --- a/gov/go.sum +++ b/gov/go.sum @@ -1,53 +1,118 @@ +bitbucket.org/creachadair/shell v0.0.6/go.mod h1:8Qqi/cYk7vPnsOePHroKXDJYmb5x7ENhtiFtfZq8K+M= bou.ke/monkey v1.0.1/go.mod h1:FgHuK96Rv2Nlf+0u1OOVDpCMdsWyOFmeeketDHE7LIg= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.60.0/go.mod h1:yw2G51M9IfRboUH61Us8GqCeF1PzPblB823Mn2q2eAU= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/spanner v1.7.0/go.mod h1:sd3K2gZ9Fd0vMPLXzeCrF6fq4i63Q7aTLW/lBIfBkIk= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= decred.org/cspp v0.3.0/go.mod h1:UygjYilC94dER3BEU65Zzyoqy9ngJfWCD2rdJqvUs2A= decred.org/dcrwallet v1.7.0 h1:U/ew00YBdUlx3rJAynt2OdKDgGzBKK4O89FijBq8iVg= decred.org/dcrwallet v1.7.0/go.mod h1:hNOGyvH53gWdgFB601/ubGRzCPfPtWnEVAi9Grs90y4= -github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM= github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/sprig v2.15.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= +github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Sereal/Sereal v0.0.0-20190618215532-0b8ac451a863 h1:BRrxwOZBolJN4gIwvZMJY1tzqBvQgpaZiQRuIDD40jM= github.com/Sereal/Sereal v0.0.0-20190618215532-0b8ac451a863/go.mod h1:D0JMgToj/WdxCgd30Kc1UcA9E+WdZoJqeVOuYW7iTBM= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/aead/siphash v0.0.0-20170329201724-e404fcfc8885/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ= +github.com/apache/beam v2.27.0+incompatible/go.mod h1:/8NX3Qi8vGstDLLaeaU7+lzVEu/ACaQhYjeefzQ0y1o= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/asdine/storm/v3 v3.0.0-20191014164809-c6fa66c747fe/go.mod h1:wncSIXIbR3lvJQhBpnwAeNPQneL5Vx2KUox2jARUdmw= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/asdine/storm/v3 v3.2.1 h1:I5AqhkPK6nBZ/qJXySdI7ot5BlXSZ7qvDY1zAn5ZJac= github.com/asdine/storm/v3 v3.2.1/go.mod h1:LEpXwGt4pIqrE/XcTvCnZHT5MgZCV6Ub9q7yQzOFWr0= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/carterjones/go-cloudflare-scraper v0.1.2/go.mod h1:maO/ygX7QWbdh/TzHqr5uR42b2BW81g/05QRx7fpw38= -github.com/carterjones/signalr v0.3.5/go.mod h1:SOGIwr/0/4GGNjHWSSginY66OVSaOeM85yWCNytdEwE= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.15+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/dajohi/goemail v1.0.0/go.mod h1:YyX3pgj9VJX6VQYu8Cbs0GYHzgFUs8q0vX5pLmFvops= +github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -63,36 +128,34 @@ github.com/decred/dcrd/addrmgr v1.0.2/go.mod h1:gNnmTuf/Xkg8ZX3j5GXbajzPrSdf5bA7 github.com/decred/dcrd/addrmgr v1.2.0/go.mod h1:QlZF9vkzwYh0qs25C76SAFZBRscjETga/K28GEE6qIc= github.com/decred/dcrd/blockchain v1.0.0/go.mod h1:nNMgOz12wlasmEJDCuSuMWYSnjDdmB4l38GKuQ/Yd+8= github.com/decred/dcrd/blockchain v1.0.1/go.mod h1:R/4XnwNOTj5IP8jQIUzrJ8zhr/7EOk09IMODwBamZoI= +github.com/decred/dcrd/blockchain v1.0.2 h1:+gJFfgv5LK+LcadyoiMln838/aU3rxDd0Smqogd6fkA= github.com/decred/dcrd/blockchain v1.0.2/go.mod h1:R/4XnwNOTj5IP8jQIUzrJ8zhr/7EOk09IMODwBamZoI= -github.com/decred/dcrd/blockchain v1.1.1 h1:CWr90sZ2YLQz84EGT+X/pzU+9AZB1eXQUy+4fsJSt5w= -github.com/decred/dcrd/blockchain v1.1.1/go.mod h1:zxi/41LgzHitpz/CZu0gxHyFHz8+ysd3lH8E3P5Uifg= github.com/decred/dcrd/blockchain/stake v1.0.0/go.mod h1:opuzF8UouYyQyRJVF00Rdd7OgWb1WKyy1pyU0QYaxz0= github.com/decred/dcrd/blockchain/stake v1.0.1/go.mod h1:hgoGmWMIu2LLApBbcguVpzCEEfX7M2YhuMrQdpohJzc= +github.com/decred/dcrd/blockchain/stake v1.0.2 h1:trUDgZsT5DYiwKu255k4hFtGiVEOAM9IDmP2GqOLYGU= github.com/decred/dcrd/blockchain/stake v1.0.2/go.mod h1:hgoGmWMIu2LLApBbcguVpzCEEfX7M2YhuMrQdpohJzc= -github.com/decred/dcrd/blockchain/stake v1.1.0 h1:kCxZdQ2/UfcD+XjE3wlCv0vLKWR9ZFtjbbTTpudb74o= -github.com/decred/dcrd/blockchain/stake v1.1.0/go.mod h1:WRuaml4bcyZYza1NT3qizlLcQwMIcAQRENvZVb2t884= github.com/decred/dcrd/blockchain/stake/v2 v2.0.0/go.mod h1:jv/rKMcZ87lhvVkHot/tElxeAYEUJ3mnKPHJ7WPq86U= github.com/decred/dcrd/blockchain/stake/v2 v2.0.1/go.mod h1:jv/rKMcZ87lhvVkHot/tElxeAYEUJ3mnKPHJ7WPq86U= +github.com/decred/dcrd/blockchain/stake/v2 v2.0.2/go.mod h1:o2TT/l/YFdrt15waUdlZ3g90zfSwlA0WgQqHV9UGJF4= github.com/decred/dcrd/blockchain/stake/v3 v3.0.0 h1:vr0o0ICjuEzg1End6YtBfwgDuPkg+FYIwGVEz18kFg0= github.com/decred/dcrd/blockchain/stake/v3 v3.0.0/go.mod h1:5GIUwsrHQCJauacgCegIR6t92SaeVi28Qls/BLN9vOw= -github.com/decred/dcrd/blockchain/standalone v1.0.0 h1:bPkFgSV7/NeZI+ZEGhaOP+XccCUBTIJb3YTf8dMwe8g= github.com/decred/dcrd/blockchain/standalone v1.0.0/go.mod h1:U5lOleFSi1nL7heSdLgEtuvg0udS1p3cvHxvLJbihfE= +github.com/decred/dcrd/blockchain/standalone v1.1.0 h1:yclvVGEY09Gf8A4GSAo+NCtL1dW2TYJ4OKp4+g0ICI0= +github.com/decred/dcrd/blockchain/standalone v1.1.0/go.mod h1:6K8ZgzlWM1Kz2TwXbrtiAvfvIwfAmlzrtpA7CVPCUPE= github.com/decred/dcrd/blockchain/standalone/v2 v2.0.0 h1:9gUuH0u/IZNPWBK9K3CxgAWPG7nTqVSsZefpGY4Okns= github.com/decred/dcrd/blockchain/standalone/v2 v2.0.0/go.mod h1:t2qaZ3hNnxHZ5kzVJDgW5sp47/8T5hYJt7SR+/JtRhI= github.com/decred/dcrd/blockchain/v3 v3.0.2/go.mod h1:LD5VA95qdb+DlRiPI8VLBimDqvlDCAJsidZ5oD6nc/U= github.com/decred/dcrd/certgen v1.0.1/go.mod h1:NxEyGwzPHak+h3tNLYAXU4vWuL98HrY9Z59hc1E3SGI= -github.com/decred/dcrd/certgen v1.0.2/go.mod h1:NxEyGwzPHak+h3tNLYAXU4vWuL98HrY9Z59hc1E3SGI= github.com/decred/dcrd/certgen v1.1.0/go.mod h1:ivkPLChfjdAgFh7ZQOtl6kJRqVkfrCq67dlq3AbZBQE= +github.com/decred/dcrd/certgen v1.1.1 h1:MYPG5jCysnbF4OiJ1++YumFEu2p/MsM/zxmmqC9mVFg= github.com/decred/dcrd/certgen v1.1.1/go.mod h1:ivkPLChfjdAgFh7ZQOtl6kJRqVkfrCq67dlq3AbZBQE= github.com/decred/dcrd/chaincfg v1.0.1/go.mod h1:O+443mQNPjci+WqWkKta3v2MgJn2u20YWy5mW3c2T7M= +github.com/decred/dcrd/chaincfg v1.1.1 h1:qRZkiA7ucsfsQPE/G/U1OnEUFozDl1MvM4ysJCUndLU= github.com/decred/dcrd/chaincfg v1.1.1/go.mod h1:UlGtnp8Xx9YK+etBTybGjoFGoGXSw2bxZQuAnwfKv6I= -github.com/decred/dcrd/chaincfg v1.2.0/go.mod h1:kpoGTMIriKn5hHRSu5b65+Q9LlGUdbQcMzGujac1BVs= -github.com/decred/dcrd/chaincfg v1.3.0/go.mod h1:kpoGTMIriKn5hHRSu5b65+Q9LlGUdbQcMzGujac1BVs= -github.com/decred/dcrd/chaincfg v1.5.1 h1:u1Xbq0VTnAXIHW5ECqrWe0VYSgf5vWHqpSiwoLBzxAQ= -github.com/decred/dcrd/chaincfg v1.5.1/go.mod h1:FukMzTjkwzjPU+hK7CqDMQe3NMbSZAYU5PAcsx1wlv0= github.com/decred/dcrd/chaincfg/chainhash v1.0.1/go.mod h1:OVfvaOsNLS/A1y4Eod0Ip/Lf8qga7VXCQjUQLbkY0Go= -github.com/decred/dcrd/chaincfg/chainhash v1.0.2 h1:rt5Vlq/jM3ZawwiacWjPa+smINyLRN07EO0cNBV6DGU= github.com/decred/dcrd/chaincfg/chainhash v1.0.2/go.mod h1:BpbrGgrPTr3YJYRN3Bm+D9NuaFd+zGyNeIKgrhCXK60= +github.com/decred/dcrd/chaincfg/chainhash v1.0.3-0.20200921185235-6d75c7ec1199 h1:G6L0a9sBulqryyyWmin7cHorxfIdg2J+xHQeJaDdNyc= +github.com/decred/dcrd/chaincfg/chainhash v1.0.3-0.20200921185235-6d75c7ec1199/go.mod h1:BpbrGgrPTr3YJYRN3Bm+D9NuaFd+zGyNeIKgrhCXK60= github.com/decred/dcrd/chaincfg/v2 v2.0.2/go.mod h1:hpKvhLCDAD/xDZ3V1Pqpv9fIKVYYi11DyxETguazyvg= github.com/decred/dcrd/chaincfg/v2 v2.1.0/go.mod h1:hpKvhLCDAD/xDZ3V1Pqpv9fIKVYYi11DyxETguazyvg= github.com/decred/dcrd/chaincfg/v2 v2.2.0/go.mod h1:hpKvhLCDAD/xDZ3V1Pqpv9fIKVYYi11DyxETguazyvg= @@ -100,19 +163,19 @@ github.com/decred/dcrd/chaincfg/v2 v2.3.0/go.mod h1:7qUJTvn+y/kswSRZ4sT2+EmvlDTD github.com/decred/dcrd/chaincfg/v3 v3.0.0 h1:+TFbu7ZmvBwM+SZz5mrj6cun9ts/6DAL5sqnsaFBHGQ= github.com/decred/dcrd/chaincfg/v3 v3.0.0/go.mod h1:EspyubQ7D2w6tjP7rBGDIE7OTbuMgBjR2F2kZFnh31A= github.com/decred/dcrd/connmgr v1.0.1/go.mod h1:jR+woh3BTbP/35v0nHMiz6GfV1RO0uF1JA+mKeXNk04= -github.com/decred/dcrd/connmgr v1.0.2/go.mod h1:jBNfQLh+454n3crgNCPrhMgZ9mVvYcMbWSCEAHsJQus= github.com/decred/dcrd/connmgr/v3 v3.0.0/go.mod h1:cPI43Aggp1lOhrVG75eJ3c3BwuFx0NhT77FK34ky+ak= -github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/crypto/blake256 v1.0.1-0.20200921185235-6d75c7ec1199 h1:sqVg68MjCKwsahuL7AbbdkUSULnZF0vGFOM8FDGscjo= +github.com/decred/dcrd/crypto/blake256 v1.0.1-0.20200921185235-6d75c7ec1199/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/crypto/ripemd160 v1.0.0/go.mod h1:F0H8cjIuWTRoixr/LM3REB8obcWkmYx0gbxpQWR8RPg= github.com/decred/dcrd/crypto/ripemd160 v1.0.1 h1:TjRL4LfftzTjXzaufov96iDAkbY2R3aTvH2YMYa1IOc= github.com/decred/dcrd/crypto/ripemd160 v1.0.1/go.mod h1:F0H8cjIuWTRoixr/LM3REB8obcWkmYx0gbxpQWR8RPg= github.com/decred/dcrd/database v1.0.0/go.mod h1:eQOhTdO3oYBshjCVxMt747CP6yKKIls6IIdqYxMRzEk= github.com/decred/dcrd/database v1.0.1/go.mod h1:ILCeyOHFew3fZ7K2B9jl+tp5qFOap/pEGoo6Yy6Wk0g= +github.com/decred/dcrd/database v1.0.2 h1:/Q+1rxvCFUcFH3FfnzVXv+3NmVPoRZ3UQmqMr2KYReA= github.com/decred/dcrd/database v1.0.2/go.mod h1:ILCeyOHFew3fZ7K2B9jl+tp5qFOap/pEGoo6Yy6Wk0g= -github.com/decred/dcrd/database v1.0.3 h1:e5Q3gDt9LwfvpZxYqFF3OVzgr8bGeC1cen+V3mv/CCw= -github.com/decred/dcrd/database v1.0.3/go.mod h1:TLxRwIV8x85+dxPTLAWu4mHg45TkKrrza5xzwOS1QtA= github.com/decred/dcrd/database/v2 v2.0.0/go.mod h1:Sj2lvTRB0mfSu9uD7ObfwCY/eJ954GFU/X+AndJIyfE= +github.com/decred/dcrd/database/v2 v2.0.1/go.mod h1:ZOaWTv3IlNqCA+y7q3q5EozgmiDOmNwCSq3ntZn2CDo= github.com/decred/dcrd/database/v2 v2.0.2 h1:t1ch4sk2qIhxGcAmWQJkFwsbqKITEcVa8E+BFpxOf7s= github.com/decred/dcrd/database/v2 v2.0.2/go.mod h1:S78KbTCCJWUTJDVTByiQuB+HmL0DM2vIMsa2WsrF9KM= github.com/decred/dcrd/dcrec v0.0.0-20180721005212-59fe2b293f69/go.mod h1:cRAH1SNk8Mi9hKBc/DHbeiWz/fyO8KWZR3H7okrIuOA= @@ -121,14 +184,13 @@ github.com/decred/dcrd/dcrec v0.0.0-20180721031028-5369a485acf6/go.mod h1:cRAH1S github.com/decred/dcrd/dcrec v0.0.0-20180801202239-0761de129164/go.mod h1:cRAH1SNk8Mi9hKBc/DHbeiWz/fyO8KWZR3H7okrIuOA= github.com/decred/dcrd/dcrec v0.0.0-20180809193022-9536f0c88fa8/go.mod h1:cRAH1SNk8Mi9hKBc/DHbeiWz/fyO8KWZR3H7okrIuOA= github.com/decred/dcrd/dcrec v0.0.0-20180816212643-20eda7ec9229/go.mod h1:cRAH1SNk8Mi9hKBc/DHbeiWz/fyO8KWZR3H7okrIuOA= -github.com/decred/dcrd/dcrec v0.0.0-20181212181811-1a370d38d671/go.mod h1:cRAH1SNk8Mi9hKBc/DHbeiWz/fyO8KWZR3H7okrIuOA= -github.com/decred/dcrd/dcrec v1.0.0 h1:W+z6Es+Rai3MXYVoPAxYr5U1DGis0Co33scJ6uH2J6o= github.com/decred/dcrd/dcrec v1.0.0/go.mod h1:HIaqbEJQ+PDzQcORxnqen5/V1FR3B4VpIfmePklt8Q8= +github.com/decred/dcrd/dcrec v1.0.1-0.20200921185235-6d75c7ec1199 h1:MkfApk/KhuIh3llbjdnTFY5G4lb7zA+EEKVKIRgAfmg= +github.com/decred/dcrd/dcrec v1.0.1-0.20200921185235-6d75c7ec1199/go.mod h1:HIaqbEJQ+PDzQcORxnqen5/V1FR3B4VpIfmePklt8Q8= github.com/decred/dcrd/dcrec/edwards v0.0.0-20180721005212-59fe2b293f69/go.mod h1:+ehP0Hk/mesyZXttxCtBbhPX23BMpZJ1pcVBqUfbmvU= github.com/decred/dcrd/dcrec/edwards v0.0.0-20180721031028-5369a485acf6/go.mod h1:+ehP0Hk/mesyZXttxCtBbhPX23BMpZJ1pcVBqUfbmvU= github.com/decred/dcrd/dcrec/edwards v0.0.0-20180809193022-9536f0c88fa8/go.mod h1:+ehP0Hk/mesyZXttxCtBbhPX23BMpZJ1pcVBqUfbmvU= github.com/decred/dcrd/dcrec/edwards v0.0.0-20180816212643-20eda7ec9229/go.mod h1:+ehP0Hk/mesyZXttxCtBbhPX23BMpZJ1pcVBqUfbmvU= -github.com/decred/dcrd/dcrec/edwards v0.0.0-20181208004914-a0816cf4301f/go.mod h1:+ehP0Hk/mesyZXttxCtBbhPX23BMpZJ1pcVBqUfbmvU= github.com/decred/dcrd/dcrec/edwards v1.0.0 h1:UDcPNzclKiJlWqV3x1Fl8xMCJrolo4PB4X9t8LwKDWU= github.com/decred/dcrd/dcrec/edwards v1.0.0/go.mod h1:HblVh1OfMt7xSxUL1ufjToaEvpbjpWvvTAUx4yem8BI= github.com/decred/dcrd/dcrec/edwards/v2 v2.0.0/go.mod h1:d0H8xGMWbiIQP7gN3v2rByWUcuZPm9YsgmnfoxgbINc= @@ -141,17 +203,15 @@ github.com/decred/dcrd/dcrec/secp256k1 v1.0.2/go.mod h1:CHTUIVfmDDd0KFVFpNX1pFVC github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.0/go.mod h1:3s92l0paYkZoIHuj4X93Teg/HB7eGM9x/zokGw+u4mY= github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0 h1:sgNeV1VRMDzs6rzyPpxyM0jp317hnwiq58Filgag2xw= github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0/go.mod h1:J70FGZSbzsjecRTiTzER+3f1KZLNaXkuv+yeFTKoxM8= +github.com/decred/dcrd/dcrjson v1.0.0 h1:50DnA0XeV2JrQXoHh43TCKmH+kz2gHjZ1Mj/Pdk7Oz0= github.com/decred/dcrd/dcrjson v1.0.0/go.mod h1:ozddIaeF+EAvZZvFuB3zpfxhyxBGfvbt22crQh+PYuI= -github.com/decred/dcrd/dcrjson v1.1.0 h1:pFpbay3cWACkgloFxWjHBwlXWG2+S2QCJJzNxL40hwg= -github.com/decred/dcrd/dcrjson v1.1.0/go.mod h1:ozddIaeF+EAvZZvFuB3zpfxhyxBGfvbt22crQh+PYuI= github.com/decred/dcrd/dcrjson/v3 v3.0.0/go.mod h1:pWYlHJ3VFidPwqD5HHiJXjfGaplif8uspAL2qFdifkY= +github.com/decred/dcrd/dcrjson/v3 v3.0.1/go.mod h1:fnTHev/ABGp8IxFudDhjGi9ghLiXRff1qZz/wvq12Mg= github.com/decred/dcrd/dcrjson/v3 v3.1.0 h1:Y2VjCXCNWbNIa52wMKEuNiU+9rUgnjYb5c1JQW6PuzM= github.com/decred/dcrd/dcrjson/v3 v3.1.0/go.mod h1:fnTHev/ABGp8IxFudDhjGi9ghLiXRff1qZz/wvq12Mg= github.com/decred/dcrd/dcrutil v1.0.0/go.mod h1:CBpbItyMKkL/4i1qPJDsE/cdSYklsWFcTYgprRZh4yk= +github.com/decred/dcrd/dcrutil v1.1.1 h1:zOkGiumN/JkobhAgpG/zfFgUoolGKVGYT5na1hbYUoE= github.com/decred/dcrd/dcrutil v1.1.1/go.mod h1:Jsttr0pEvzPAw+qay1kS1/PsbZYPyhluiNwwY6yBJS4= -github.com/decred/dcrd/dcrutil v1.2.0/go.mod h1:tUNHS2gj7ApeEVS8gb6O+4wJW7w3O2MSRyRdcjW1JxU= -github.com/decred/dcrd/dcrutil v1.4.0 h1:xD5aUqysGQnsnP1c9J0kGeW8lDIwFGC3ja/gE3HnpCs= -github.com/decred/dcrd/dcrutil v1.4.0/go.mod h1:Bs74gm1jQ9ZAbmEh9FWOEZ1HQzlMg5iPATDMzMnCMlQ= github.com/decred/dcrd/dcrutil/v2 v2.0.0/go.mod h1:gUshVAXpd51DlcEhr51QfWL2HJGkMDM1U8chY+9VvQg= github.com/decred/dcrd/dcrutil/v2 v2.0.1/go.mod h1:JdEgF6eh0TTohPeiqDxqDSikTSvAczq0J7tFMyyeD+k= github.com/decred/dcrd/dcrutil/v3 v3.0.0 h1:n6uQaTQynIhCY89XsoDk2WQqcUcnbD+zUM9rnZcIOZo= @@ -161,31 +221,33 @@ github.com/decred/dcrd/gcs v1.0.1/go.mod h1:YwutGzusSdJM79CJtxCo9t7WRCvnkLtWSD19 github.com/decred/dcrd/gcs v1.0.2/go.mod h1:eLCvrzUsWro48TlTyrmFcZAZqnllYFz0vEv5VZtufF4= github.com/decred/dcrd/gcs v1.1.0 h1:djuYzaFUzUTJR+6ulMSRZOQ+P9rxtIyuxQeViAEfB8s= github.com/decred/dcrd/gcs v1.1.0/go.mod h1:yBjhj217Vw5lw3aKnCdHip7fYb9zwMos8bCy5s79M9w= +github.com/decred/dcrd/gcs/v2 v2.0.0/go.mod h1:3XjKcrtvB+r2ezhIsyNCLk6dRnXRJVyYmsd1P3SkU3o= github.com/decred/dcrd/gcs/v2 v2.1.0 h1:foECqwfE3UJztU4CYtqUYqvR254x1Z9clXVfNdOjBQ8= github.com/decred/dcrd/gcs/v2 v2.1.0/go.mod h1:MbnJOINFcp42NMRAQ+CjX/xGz+53AwNgMzKZhwBibdM= +github.com/decred/dcrd/hdkeychain v1.1.0 h1:6bFdL672dCmtg/JEzb3Jw0dTRO2jLxcA7BK2J+JaoUM= github.com/decred/dcrd/hdkeychain v1.1.0/go.mod h1:zyUZtZ3PdnTPHt2XUr1x76b8ZuiM+9aVkP8Rq8Scp1k= -github.com/decred/dcrd/hdkeychain v1.1.1/go.mod h1:CLBVXLoO63fIiqkv38KR23zXGSgrfiAWOybOKTneLhA= github.com/decred/dcrd/hdkeychain/v2 v2.0.1/go.mod h1:qPv+vTla19liVHFuXVnQ70dMI4ERPCniDXbV5RzwQiM= +github.com/decred/dcrd/hdkeychain/v2 v2.1.0/go.mod h1:DR+lD4uV8G0i3c9qnUJwjiGaaEWK+nSrbWCz1BRHBL8= +github.com/decred/dcrd/hdkeychain/v3 v3.0.0 h1:hOPb4c8+K6bE3a/qFtzt2Z2yzK4SpmXmxvCTFp8vMxI= github.com/decred/dcrd/hdkeychain/v3 v3.0.0/go.mod h1:Vz7PJSlLzhqmOR2lmjGD9JqAZgmUnM8P6r8hg7U4Zho= github.com/decred/dcrd/mempool v1.0.1/go.mod h1:r+/DGiiluXi1EyMCCPPH58Qu+rsr8nZv0DialAG5VZQ= -github.com/decred/dcrd/mempool v1.1.1/go.mod h1:u1I2KRv9UHhx2crlbZXYoLDabWyQ8VnnHDSG53UdhCA= github.com/decred/dcrd/mining v1.0.0/go.mod h1:VA5H4zhJgXb8LK5lqM5H58dhMRXJRcaQQoX3G8QRpP8= github.com/decred/dcrd/mining v1.0.1/go.mod h1:+CSOLPi7TM8OlQg7mJ7XzWLXCDb4nHK8R6cvXOzhEoU= -github.com/decred/dcrd/mining v1.1.0/go.mod h1:NQEtX604XgNwKcPFId1hVTTiBqmVQDlnqV1yNqGl4oU= -github.com/decred/dcrd/rpc/jsonrpc/types v1.0.0 h1:d5ptnjuSADTQMa3i83VpeJNoMRTOJZZBqk7P+E41VXM= github.com/decred/dcrd/rpc/jsonrpc/types v1.0.0/go.mod h1:0dwmpIP21tJxjg/UuUHWIFMbfoLv2ifCBMokNKlOxpo= +github.com/decred/dcrd/rpc/jsonrpc/types v1.0.1 h1:sWsGtWzdmrna6aysDCHwjANTJh+Lxt2xp6S10ahP79Y= +github.com/decred/dcrd/rpc/jsonrpc/types v1.0.1/go.mod h1:dJUp9PoyFYklzmlImpVkVLOr6j4zKuUv66YgemP2sd8= +github.com/decred/dcrd/rpc/jsonrpc/types/v2 v2.0.0/go.mod h1:c5S+PtQWNIA2aUakgrLhrlopkMadcOv51dWhCEdo49c= github.com/decred/dcrd/rpc/jsonrpc/types/v2 v2.3.0 h1:KZ2zihwY5Mx6EeYwEA3bL3k+qDXdCraQL+iDIG1BP5k= github.com/decred/dcrd/rpc/jsonrpc/types/v2 v2.3.0/go.mod h1:krn89ZOgSa8yc7sA4WpDK95p61NnjNWFkNlMnGrKbMc= +github.com/decred/dcrd/rpcclient v1.0.1 h1:mSkVtOQKXnMJ2P08xPFnD2J9w54+YFQuMeBd5tC9iBI= github.com/decred/dcrd/rpcclient v1.0.1/go.mod h1:tApXK3wwrAQtz7lcXeeqBwuktUZesvrFfvhAdedYqdM= -github.com/decred/dcrd/rpcclient v1.1.0 h1:nQZ1qOJaLYoOTM1oQ2dLaqocb5TWI7gNBK+BTY7UVXk= -github.com/decred/dcrd/rpcclient v1.1.0/go.mod h1:SCwBs4d+aqRV2ChnriIZ1y/LgNVHG/2ieEC1vIop82s= github.com/decred/dcrd/rpcclient/v4 v4.0.0/go.mod h1:DNGwfiL5H+K/pk3hVB0z5ypRdiDXMssR+YEqDUEXCQo= +github.com/decred/dcrd/rpcclient/v5 v5.0.0/go.mod h1:lg7e2kpulSpynHkS2JXJ+trQ4PWHaHLQcp/Q0eSIvBc= github.com/decred/dcrd/rpcclient/v6 v6.0.2 h1:bPHPeKGrPZPsHDSRIJxj5xhqoxwM5R7+OsEZXFpDxPk= github.com/decred/dcrd/rpcclient/v6 v6.0.2/go.mod h1:t6ECC72j2xWQ323poL85IFNq0EUfcSTfwL8j7jDJ6mw= github.com/decred/dcrd/txscript v1.0.0/go.mod h1:9byvrOaBSBVVnDG7Cm0JgN8bZytl1oi9Ba245VBeI18= +github.com/decred/dcrd/txscript v1.0.1 h1:IMgxZFCw3AyG4EbKwywE3SDNshOSHsoUK1Wk/5GqWJ0= github.com/decred/dcrd/txscript v1.0.1/go.mod h1:FqUX07Y+u3cJ1eIGPoyWbJg+Wk1NTllln/TyDpx9KnY= -github.com/decred/dcrd/txscript v1.0.2 h1:kzJZDuteyzvI15VNhtgFHxeeq210RTkFyfzN7d+1iPo= -github.com/decred/dcrd/txscript v1.0.2/go.mod h1:hmUOHFlOjU7H6T/czt6kurWwXJvGPGKKGtXoft6w/qY= github.com/decred/dcrd/txscript/v2 v2.0.0/go.mod h1:WStcyYYJa+PHJB4XjrLDRzV96/Z4thtsu8mZoVrU6C0= github.com/decred/dcrd/txscript/v2 v2.1.0/go.mod h1:XaJAVrZU4NWRx4UEzTiDAs86op1m8GRJLz24SDBKOi0= github.com/decred/dcrd/txscript/v3 v3.0.0 h1:74NmirXAIskbGP0g9OWtrmN7OxDbWJ9G73a5uoxTkcM= @@ -196,173 +258,233 @@ github.com/decred/dcrd/wire v1.2.0/go.mod h1:/JKOsLInOJu6InN+/zH5AyCq3YDIOW/Eqcf github.com/decred/dcrd/wire v1.3.0/go.mod h1:fnKGlUY2IBuqnpxx5dYRU5Oiq392OBqAuVjRVSkIoXM= github.com/decred/dcrd/wire v1.4.0 h1:KmSo6eTQIvhXS0fLBQ/l7hG7QLcSJQKSwSyzSqJYDk0= github.com/decred/dcrd/wire v1.4.0/go.mod h1:WxC/0K+cCAnBh+SKsRjIX9YPgvrjhmE+6pZlel1G7Ro= -github.com/decred/dcrdata/api/types/v4 v4.0.2/go.mod h1:9Jnyp9FLSfhx7jlJSyKJaeOJ/33LAOL+uvE1T0bcOns= github.com/decred/dcrdata/api/types/v4 v4.0.4/go.mod h1:CCu2Itqv/K3lqFxqSYDC49XWu5OuZRvNFkPiFHb0tYU= -github.com/decred/dcrdata/blockdata/v4 v4.0.4-0.20191018131105-43d40fcf6525/go.mod h1:P8HsR6L6RuYyuJNFRxke4X67YeJ91rOBeSAb8ZI0jJ8= -github.com/decred/dcrdata/db/dbtypes/v2 v2.1.2/go.mod h1:Gb3NmWxL+3nsy9f7kmnLXwVUmHp0oHtn+WblrKIM3DM= -github.com/decred/dcrdata/db/dbtypes/v2 v2.1.3-0.20191018131657-8f5538d3b4b3/go.mod h1:F0BY7RbDsTFUfPOK/q9NkubZfKt7LxD06wCCvC5gywU= github.com/decred/dcrdata/db/dbtypes/v2 v2.1.4/go.mod h1:UF4KWxcCYhdXqaTwbA2Mb10os4H0UFSZaiu5eeMWQT8= -github.com/decred/dcrdata/dcrrates v1.1.1/go.mod h1:r/d8jU/E1rA+hska5xMmkpsyUzMupLGuTxXQ9GhBD7Y= -github.com/decred/dcrdata/exchanges/v2 v2.0.2/go.mod h1:VZhPe44SLhhbQSniNUwv/CNYwgghPzBRNXRPNljby6g= -github.com/decred/dcrdata/explorer/types/v2 v2.0.2/go.mod h1:6cvEUaSYkyGoiqgyh/3N2I2EzXjb6TRBact3yi8Gtdo= -github.com/decred/dcrdata/explorer/types/v2 v2.0.3-0.20191018131657-8f5538d3b4b3/go.mod h1:ibWnzMcQkoE547UD0LI29i5v5jaoyKpeLeU7Cd5tIkY= -github.com/decred/dcrdata/mempool/v4 v4.0.4-0.20191018131657-8f5538d3b4b3/go.mod h1:ysaPY8oraR1Hv+xTaTeF6QK9TaGDC5eS56KN7AAd7+Y= -github.com/decred/dcrdata/pubsub/types/v3 v3.0.2/go.mod h1:Rycd3SPR2dC9WIBQhnWFqta7uRK9yKqJDz70jz880no= -github.com/decred/dcrdata/pubsub/types/v3 v3.0.3-0.20191018131657-8f5538d3b4b3/go.mod h1:/NDVANaxXK2Fvq1+WPsezNmMniA5G2iZHtLF9DKTK2E= -github.com/decred/dcrdata/pubsub/types/v3 v3.0.3-0.20191018133341-23a17268b383/go.mod h1:/NDVANaxXK2Fvq1+WPsezNmMniA5G2iZHtLF9DKTK2E= -github.com/decred/dcrdata/pubsub/v3 v3.0.4-0.20191018133341-23a17268b383/go.mod h1:bSYDdKxj5tUA31Jm9HpmyPg/YR6qERSrQH81gPpyOj0= -github.com/decred/dcrdata/rpcutils/v2 v2.0.3/go.mod h1:bN6Mwdd1udV0/0QJiYOG10ChEao1FFnM5TBeoF43mu8= +github.com/decred/dcrdata/db/dbtypes/v2 v2.2.1/go.mod h1:zVQdtnKZqlmop/C+qCb1vGU9ab3CGC6gohM+AWTQbYg= github.com/decred/dcrdata/semver v1.0.0/go.mod h1:z+nQqiAd9fYkHhBLbejysZ2FPHtgkrErWDgMf+JlZWE= -github.com/decred/dcrdata/stakedb/v3 v3.0.4-0.20191016213257-fb798036d9dc/go.mod h1:8oDaFvlGbOocULLymbQ40Ju7qQgfPRbIyV5wxUFFHL0= -github.com/decred/dcrdata/txhelpers/v3 v3.0.2/go.mod h1:iukqEl5AR6BdippUWKsC8OzaV9TW/KMBYpIwKv8IkW0= -github.com/decred/dcrdata/txhelpers/v3 v3.0.3-0.20191018131657-8f5538d3b4b3/go.mod h1:t/5u8aHI2Z/ey6SQ3G0/jGwPweUz/uojF2dT2ePpmEw= github.com/decred/dcrdata/txhelpers/v3 v3.0.4/go.mod h1:tKEDhoO+TbYrFrx+5qKZDxcla8ELQFYs4f5+8gL4cuY= +github.com/decred/dcrdata/txhelpers/v4 v4.0.1/go.mod h1:cUJbgsIzzI42llHDS0nkPlG49vPJ0cW6IZGbfu5sFrA= +github.com/decred/dcrtime v0.0.0-20191018193024-8d8b4ef0458e h1:sNDR7vx6gaA3WD+WoEofTvtdjfwHAiogtjB3kt8iFco= github.com/decred/dcrtime v0.0.0-20191018193024-8d8b4ef0458e/go.mod h1:IyZnyBE3E6RBFsEjwEs21FrO/UsrLrL15hUnpZZQxpU= +github.com/decred/dcrtime/api/v2 v2.0.0-20200912200806-b1e4dbc46be9/go.mod h1:JdIX208vnNj4TdU6hDRaN+ccxmxp1I1R6sWGZNK1BAQ= github.com/decred/dcrwallet v1.2.2/go.mod h1:BrSus0F+Rx8UhvPNBfuRMIjRJBNrW2sLspN9iQR5hm8= -github.com/decred/dcrwallet v1.2.3-0.20190128160919-849f7c01c12d/go.mod h1:jtNUWAO6lg2t2UHOlT9fmjuxD8os9JMljZNEXaw95Tg= github.com/decred/dcrwallet/chain v1.0.0/go.mod h1:KpZFaKlKajfUZt36+RmBn2HKwTbwoa3yt9HPALqlShI= -github.com/decred/dcrwallet/chain v1.1.1/go.mod h1:2kA82rBDkCKOSYFV+Q14RZNCuYwdaQ9uO/c+RixqRNs= github.com/decred/dcrwallet/deployments v1.0.0/go.mod h1:0bWER/DAYoGbzkWzbUf6k2agW4YkSyvNLZDhBGThz/4= -github.com/decred/dcrwallet/deployments v1.1.0/go.mod h1:8Sasryu8SX23Jvqr6maZ7MoS7wFIGXupWzbsVtcZsUg= github.com/decred/dcrwallet/errors v1.0.0/go.mod h1:XUm95dWmm9XmQGvneBXJkkIaFeRsQVBB6ni/KTy1hrY= -github.com/decred/dcrwallet/errors v1.0.1/go.mod h1:XUm95dWmm9XmQGvneBXJkkIaFeRsQVBB6ni/KTy1hrY= github.com/decred/dcrwallet/internal/helpers v1.0.0/go.mod h1:FsihtjCyFrGL6gdmkxBWTYQ1CUgbfM9tyinYNOzLnlk= -github.com/decred/dcrwallet/internal/helpers v1.0.1/go.mod h1:qIXcze8VZ+A3sEgZou7PTOe4Vsnmks54SGTSGZ6084g= github.com/decred/dcrwallet/internal/zero v1.0.0/go.mod h1:vULuNLRTcnifKCepcIxUDL4jrR3rJOwVR9UDH89Qpms= -github.com/decred/dcrwallet/internal/zero v1.0.1/go.mod h1:mXUIsKATE1pIaNAJQ4lhSTX6c9N5sYoSrlScgRCaMJs= github.com/decred/dcrwallet/lru v1.0.0/go.mod h1:jEty7mdT5VaaV06DEV2Avv0R3HpGvUwvDW4lw8ECtiY= github.com/decred/dcrwallet/p2p v1.0.0/go.mod h1:b1CLZAkl/K5dr5I5B4SdFT8FrE11jSkfA4VAA862ACA= -github.com/decred/dcrwallet/p2p v1.0.1/go.mod h1:FsoAR0cBOLW3VKMg+Tdx+wdSezR7g8NGOdz4fx6gtpM= github.com/decred/dcrwallet/pgpwordlist v1.0.0/go.mod h1:Fek3uYn+9DnEFIreA/8PnTIXUl2lBO64JpEBkL9BXtk= github.com/decred/dcrwallet/rpc/jsonrpc/types v1.1.0/go.mod h1:xUT7XXATLOzE0pwwmvgfRWtZdrB+PsWFilo+jkH5/Ig= +github.com/decred/dcrwallet/rpc/jsonrpc/types v1.3.0/go.mod h1:Xvekb43GtfMiRbyIY4ZJ9Uhd9HRIAcnp46f3q2eIExU= github.com/decred/dcrwallet/rpc/walletrpc v0.1.0/go.mod h1:Zp1ZFTCUo7S6MJvUyS5tYfaDUxGAMHkZ+vbsLgAdd4A= github.com/decred/dcrwallet/rpc/walletrpc v0.2.0/go.mod h1:uhjgcju9lSb/+42Ms4VY1zpBOxstCLM5wVlL3mq/SYc= github.com/decred/dcrwallet/spv v1.0.0/go.mod h1:lz39nz9P/HVoxYa4XAT6ithyR3WgdF0oVu4jtFwnCxE= -github.com/decred/dcrwallet/spv v1.1.0/go.mod h1:HYfF+A1F+Apf0WPT6QRsG/gfvaFQmWObAytq8pWc6ME= github.com/decred/dcrwallet/ticketbuyer v1.0.0/go.mod h1:mrAlRjOJ6txO8Zyqo5koxVOMEYLK2POUX35a/QcKN8g= -github.com/decred/dcrwallet/ticketbuyer v1.0.2/go.mod h1:oDHY0TOFIaQjZ11TJbgztC5tt1zi6wKoRmyQMmwfft4= github.com/decred/dcrwallet/ticketbuyer/v2 v2.0.0/go.mod h1:VKo2PjXAlF/E46tSBKrIgqKbVcHVLfM5ACyOehT1unA= -github.com/decred/dcrwallet/ticketbuyer/v2 v2.0.1/go.mod h1:ngtx8I/+Jo+U+E/5XjwCkmU55wCGtUbaDnCP5qazNGM= github.com/decred/dcrwallet/validate v1.0.0/go.mod h1:zHIlcrjAWl6LK+X+R7jc3F9wIM/qxjtMjG/mdEwt4tY= github.com/decred/dcrwallet/validate v1.0.1/go.mod h1:9DCtLFnnTOC/7PKkF7jehvDyHkfUBl41ZbcT1u4PmQM= -github.com/decred/dcrwallet/validate v1.0.2/go.mod h1:1ur2sRZkQ23ECalUKdwgx6rdIiP8rIiaSQAz1Y9LQsI= github.com/decred/dcrwallet/version v1.0.0/go.mod h1:rXeMsUaI03WtlQrSol7Q7sJ8HBOB+tZvT7YQRXD5Y7M= -github.com/decred/dcrwallet/version v1.0.1/go.mod h1:rXeMsUaI03WtlQrSol7Q7sJ8HBOB+tZvT7YQRXD5Y7M= github.com/decred/dcrwallet/wallet v1.0.0/go.mod h1:VWRnpNFRiKPo7FUPbzj0t5ElcGxNXMPIa4vGcGe94uM= -github.com/decred/dcrwallet/wallet v1.1.0/go.mod h1:g4OzDG7jpsRqTDP3bHiA0LIEZFx81accYPCkO1DBNT8= -github.com/decred/dcrwallet/wallet v1.2.0/go.mod h1:ItOhnw3C4znuLQVWACSq8jCLy221v9X0Xo0b/j5WqgU= -github.com/decred/dcrwallet/wallet v1.3.0/go.mod h1:ItOhnw3C4znuLQVWACSq8jCLy221v9X0Xo0b/j5WqgU= github.com/decred/dcrwallet/walletseed v1.0.0/go.mod h1:xSF6hZW+5Xhm0jJFsI5jQSfViuZUQJoDXa/cQxtgncs= -github.com/decred/dcrwallet/walletseed v1.0.1/go.mod h1:ENlwTabC2JVmT4S1eCP44fnwX4+9y2RLsnfSU21CJ+4= github.com/decred/go-socks v1.0.0/go.mod h1:sDhHqkZH0X4JjSa02oYOGhcGHYp12FsY1jQ/meV8md0= github.com/decred/go-socks v1.1.0 h1:dnENcc0KIqQo3HSXdgboXAHgqsCIutkqq6ntQjYtm2U= github.com/decred/go-socks v1.1.0/go.mod h1:sDhHqkZH0X4JjSa02oYOGhcGHYp12FsY1jQ/meV8md0= -github.com/decred/politeia v0.0.0-20191031182202-b33af07598f2 h1:xF5UazYefAzh91yvD6Rv6zkogZb+kJyIhx8mX89giuE= -github.com/decred/politeia v0.0.0-20191031182202-b33af07598f2/go.mod h1:biL6LECQ+6xwYHEJocudqMK+A1O0XbBshFkvFziFZgg= +github.com/decred/politeia v1.0.1 h1:MehAIlMLZZBLlkP8LuAlckx0xmIpIZJTYkXOkRGxdA8= +github.com/decred/politeia v1.0.1/go.mod h1:bWvCogzo8MzyPos4tX9V/5FXhVRUwcd6ycZhElcDLE0= github.com/decred/slog v1.0.0/go.mod h1:zR98rEZHSnbZ4WHZtO0iqmSZjDLKhkXfrPTZQKtAonQ= github.com/decred/slog v1.1.0 h1:uz5ZFfmaexj1rEDgZvzQ7wjGkoSPjw2LCh8K+K1VrW4= github.com/decred/slog v1.1.0/go.mod h1:kVXlGnt6DHy2fV5OjSeuvCJ0OmlmTF6LFpEPMu/fOY0= -github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM= -github.com/dgraph-io/badger v1.5.5-0.20190214192501-3196cc1d7a5f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= +github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/dgraph-io/badger v1.6.2/go.mod h1:JW2yswe3V058sS0kZ2h/AXeDSqFjxnZcRrVH//y2UQE= github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/elazarl/goproxy v0.0.0-20181111060418-2ce16c963a8a/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.0.14/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fullstorydev/grpcurl v1.6.0/go.mod h1:ZQ+ayqbKMJNhzLmbpCiurTVlaK2M/3nqZCxaQ2Ze/sM= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/trillian v1.2.1/go.mod h1:YPmUVn5NGwgnDUgqlVyFGMTgaWlnSvH7W5p+NdOG8UA= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200507031123-427632fa3b1c/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/trillian v1.3.13 h1:V0avmojBPY7YAlcd/nUVvNRprU28tRsahPNxIedqekU= +github.com/google/trillian v1.3.13/go.mod h1:8y3zC8XuqFxsslWPkP0r3sprERfFf7hCWmicL0yHZNI= +github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/csrf v1.6.0/go.mod h1:7tSf8kmjNYr7IWDCYhd3U8Ck34iQ/Yw5CJu7bAkHEGI= +github.com/gorilla/csrf v1.6.2/go.mod h1:7tSf8kmjNYr7IWDCYhd3U8Ck34iQ/Yw5CJu7bAkHEGI= github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY= github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= -github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.3/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c h1:fEE5/5VNnYUoBOj2I9TP8Jc+a7lge3QWn9DKE7NCwfc= github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c/go.mod h1:ObS/W+h8RYb1Y7fYivughjxojTmIu5iAIjSrSLCLeqE= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= +github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.1-0.20200711081900-c17162fe8fd7/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jinzhu/gorm v1.9.10/go.mod h1:Kh6hTsSGffh4ui079FHrR5Gg+5D0hgihqDcsDN2BBJY= +github.com/jhump/protoreflect v1.6.1/go.mod h1:RZQ/lnuN+zqeRVpQigTwO6o0AJUkxbnSnpuG7toUTG4= +github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZT/Qs= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jrick/bitset v1.0.0/go.mod h1:ZOYB5Uvkla7wIEY4FEssPVi3IQXa02arznRaYaAEPe4= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/jrick/wsrpc/v2 v2.3.2/go.mod h1:XPYs8BnRWl99lCvXRM5SLpZmTPqWpSOPkDIqYTwDPfU= github.com/jrick/wsrpc/v2 v2.3.4/go.mod h1:XPYs8BnRWl99lCvXRM5SLpZmTPqWpSOPkDIqYTwDPfU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= @@ -371,25 +493,67 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.2/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/letsencrypt/pkcs11key/v4 v4.0.0/go.mod h1:EFUvBDay26dErnNb70Nd0/VW3tJiIbETBPTl9ATXQag= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/marcopeereboom/sbox v1.0.0/go.mod h1:V9e7t7oKphNfXymk7Lqvbo9mZiVjmCt8vBHnROcpCSY= -github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/marcopeereboom/sbox v1.1.0 h1:IiVHCi5f+nGRiMX551wnDk5ce+IEd3dWVH7ycf2uU2M= +github.com/marcopeereboom/sbox v1.1.0/go.mod h1:u2fh4EbQDXQXXzGypWkf2nMn2TnsqA23t224mii7oog= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007/go.mod h1:m2XC9Qq0AlmmVksL6FktJCdTYyLk7V3fKyp0sl1yWQo= +github.com/mwitkow/go-proto-validators v0.2.0/go.mod h1:ZfA1hW+UH/2ZHOWvQ3HnQaU0DtnpXu850MZiy+YUgcc= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/nishanths/predeclared v0.0.0-20190419143655-18a43bb90ffc/go.mod h1:62PewwiQTlm/7Rj+cxVYqZvDIUc+JjZq6GHAC1fsObQ= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= @@ -399,50 +563,95 @@ github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/otiai10/copy v1.0.1/go.mod h1:8bMCJrAqOtN/d9oyh5HR7HhLQMvcGMpGdwRDYsfOCHc= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v0.0.0-20190513014714-f5a3d24e5776/go.mod h1:3HNVkVOU7vZeFXocWuvtcS0XSFLcf2XUSDHkq9t1jU4= github.com/otiai10/mint v1.2.3/go.mod h1:YnfyPNhBvnY8bW4SGQHCs/aAFhkgySlMZbrF5U0bOVw= github.com/otiai10/mint v1.2.4/go.mod h1:d+b7n/0R3tdyUYYylALXpWQ/kTN+QobSq/4SRGBkR3M= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/pseudomuto/protoc-gen-doc v1.3.2/go.mod h1:y5+P6n3iGrbKG+9O04V5ld71in3v/bX88wUwgt+U8EA= +github.com/pseudomuto/protokit v0.2.0/go.mod h1:2PdH30hxVHsup8KpBTOXTBeMVhJZVio3Q8ViKSAXT0Q= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v0.0.0-20170130113145-4d4bfba8f1d1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= @@ -451,46 +660,97 @@ github.com/subosito/gozaru v0.0.0-20190625071150-416082cce636/go.mod h1:LIpwO1yA github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca h1:Ld/zXl5t4+D69SiV4JoN7kkfvJdOWlPpfxrzxpLMoUk= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/vmihailenco/msgpack v4.0.1+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -go.etcd.io/bbolt v1.3.0/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200819165624-17cef6e3e9d5/go.mod h1:skWido08r9w6Lq/w70DO5XYIKMu4QFu1+4VsqLQuJy8= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +golang.org/x/crypto v0.0.0-20180501155221-613d6eafa307/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180718160520-a2144134853f/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180808211826-de0752318171/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180808004115-f9ce57c11b24/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181207154023-610586996380/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -498,123 +758,283 @@ golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190415214537-1da14a5a36f2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191105084925-a882066a44e0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180810070207-f0d5e33068cb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180816055513-1c9583448a9c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181206074257-70b957f3b65e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181212120007-b05ddf57801d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190416124237-ebb4019f01c9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190614084037-d442b75600c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210309074719-68d13333faf2 h1:46ULzRKLh1CwgRq2dC5SlBzEqqNCi8rreOZnNrbqcIY= +golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200630154851-b2d8b0336632/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200706234117-b22de6825cf7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= +google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180808183934-383e8b2c3b9e/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181107211654-5fc9ac540362/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190415143225-d1146b9035b9/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200626011028-ee7919e894b5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200707001353-8e8330bf89df h1:HWF6nM8ruGdu1K8IXFR+i2oT3YP+iBfZzCbC9zUfcWo= +google.golang.org/genproto v0.0.0-20200707001353-8e8330bf89df/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.0/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.32.0 h1:zWTV+LMdc3kaiJMSTOFz2UgSBgx8RNQoTGiZu3fR9S0= google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/gov/politeia/piclient/piclient.go b/gov/politeia/piclient/piclient.go deleted file mode 100644 index 4188f54f8..000000000 --- a/gov/politeia/piclient/piclient.go +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (c) 2019-2021, The Decred developers -// See LICENSE for details. - -// Package piclient handles the http requests made to Politeia APIs. -package piclient - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "regexp" - - pitypes "github.com/decred/dcrdata/gov/v4/politeia/types" - piapi "github.com/decred/politeia/politeiawww/api/www/v1" -) - -// HandleGetRequests accepts a http client and API URL path as arguments. If the -// parameters are valid, a GET request is made to the API URL passed. The body -// returned is decoded into []byte and returned. -func HandleGetRequests(client *http.Client, URLPath string) ([]byte, error) { - if client == nil { - return nil, fmt.Errorf("invalid http client was passed") - } - - if URLPath == "" { - return nil, fmt.Errorf("empty API URL is not supported") - } - - response, err := client.Get(URLPath) - if err != nil || response == nil { - return nil, fmt.Errorf("request failed: %v", err) - } - - // Check if valid status code (200 Ok) was returned. - if response.StatusCode != http.StatusOK { - return nil, fmt.Errorf("request (%s) failed with status code: %s", - URLPath, response.Status) - } - - defer response.Body.Close() - - return ioutil.ReadAll(response.Body) -} - -// DropURLRegex replaces "{token:[A-z0-9]{64}}" in a URL with provided the parameter. -func DropURLRegex(URLPath, param string) string { - r := regexp.MustCompile(`\{token:\[A-z0-9]\{64\}}`) - return r.ReplaceAllLiteralString(URLPath, param) -} - -// RetrieveAllProposals returns a list of Proposals whose maximum count is defined -// by piapi.ProposalListPageSize. Data returned is queried from Politeia API. -func RetrieveAllProposals(client *http.Client, APIRootPath, URLParams string) ( - *pitypes.Proposals, error) { - // Constructs the full vetted proposals API URL - URLpath := APIRootPath + piapi.RouteAllVetted + URLParams - data, err := HandleGetRequests(client, URLpath) - if err != nil { - return nil, err - } - - var publicProposals pitypes.Proposals - err = json.Unmarshal(data, &publicProposals) - if err != nil || len(publicProposals.Data) == 0 { - return &publicProposals, err - } - - // Constructs the full vote status API URL - URLpath = APIRootPath + piapi.RouteAllVoteStatus + URLParams - data, err = HandleGetRequests(client, URLpath) - if err != nil { - return nil, err - } - - var votesInfo pitypes.Votes - err = json.Unmarshal(data, &votesInfo) - if err != nil { - return nil, err - } - - // Append the votes status information to the respective proposals if it exists. - for _, val := range publicProposals.Data { - for k := range votesInfo.Data { - if val.TokenVal == votesInfo.Data[k].Token { - val.ProposalVotes = votesInfo.Data[k] - // exits the second loop after finding a match. - break - } - } - } - - return &publicProposals, nil -} - -// RetrieveProposalByToken returns a single proposal identified by the token -// hash provided if it exists. Data returned is queried from Politeia API. -func RetrieveProposalByToken(client *http.Client, APIRootPath, token string) (*pitypes.Proposal, error) { - // Constructs the full proposal's URl and fetch is data. - proposalRoute := APIRootPath + DropURLRegex(piapi.RouteProposalDetails, token) - data, err := HandleGetRequests(client, proposalRoute) - if err != nil { - return nil, fmt.Errorf("retrieving %s proposal details failed: %v", token, err) - } - - var proposal pitypes.Proposal - err = json.Unmarshal(data, &proposal) - if err != nil { - return nil, err - } - - // Check if null proposal data was returned as part of the proposal details. - if proposal.Data == nil { - return nil, fmt.Errorf("invalid proposal with null data found for %s", token) - } - - // Constructs the full votes status URL and fetch its data. - votesStatusRoute := APIRootPath + DropURLRegex(piapi.RouteVoteStatus, token) - data, err = HandleGetRequests(client, votesStatusRoute) - if err != nil { - return nil, fmt.Errorf("retrieving %s proposal vote status failed: %v", token, err) - } - - err = json.Unmarshal(data, &proposal.Data.ProposalVotes) - if err != nil { - return nil, err - } - - return &proposal, nil -} diff --git a/gov/politeia/piclient/piclient_test.go b/gov/politeia/piclient/piclient_test.go deleted file mode 100644 index ed09d41e1..000000000 --- a/gov/politeia/piclient/piclient_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package piclient - -import ( - "fmt" - "net/http" - "net/http/httptest" - "reflect" - "strconv" - "testing" -) - -// TestHandleGetRequests Tests the HandleGetRequests functionality. -func TestHandleGetRequests(t *testing.T) { - type testsData struct { - // Inputs - client *http.Client - _APIURLPath string - - // Outputs - data []byte - errMsg string - } - - // This is a mock server that should handle the requests locally. - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - fmt.Fprintln(w, "OK") - })) - - testClient := server.Client() - testURL := server.URL - - td := []testsData{ - {nil, "", []byte(""), "invalid http client was passed"}, - {testClient, "", []byte(""), "empty API URL is not supported"}, - {nil, testURL, []byte(""), "invalid http client was passed"}, - {testClient, testURL, []byte("OK"), ""}, - } - - // tests if the expected result is returned. - for i, item := range td { - t.Run("Test_"+strconv.Itoa(i), func(t *testing.T) { - results, err := HandleGetRequests(item.client, item._APIURLPath) - if err != nil { - if err.Error() != item.errMsg { - t.Fatalf("expected the error message to be '%s' but found '%v'", item.errMsg, err) - } - } else { - if item.errMsg != "" { - t.Fatalf("expected no error message but found '%s'", item.errMsg) - } - } - - if reflect.DeepEqual(results, item.data) { - t.Fatalf("expected the result returned to be '%+v' but found '%+v'", item.data, results) - } - }) - } -} diff --git a/gov/politeia/proposals.go b/gov/politeia/proposals.go index 39e994a47..5d6ef6a75 100644 --- a/gov/politeia/proposals.go +++ b/gov/politeia/proposals.go @@ -1,16 +1,13 @@ // Copyright (c) 2019-2021, The Decred developers // See LICENSE for details. -// Package politeia manages Politeia proposals and the voting that is -// coordinated by the Politeia server and anchored on the blockchain. package politeia import ( "errors" "fmt" - "net/http" "os" - "regexp" + "sort" "strconv" "strings" "sync/atomic" @@ -18,10 +15,12 @@ import ( "github.com/asdine/storm/v3" "github.com/asdine/storm/v3/q" - "github.com/decred/dcrdata/gov/v4/politeia/piclient" pitypes "github.com/decred/dcrdata/gov/v4/politeia/types" "github.com/decred/dcrdata/v6/semver" - piapi "github.com/decred/politeia/politeiawww/api/www/v1" + commentsv1 "github.com/decred/politeia/politeiawww/api/comments/v1" + recordsv1 "github.com/decred/politeia/politeiawww/api/records/v1" + ticketvotev1 "github.com/decred/politeia/politeiawww/api/ticketvote/v1" + piclient "github.com/decred/politeia/politeiawww/client" ) var ( @@ -36,32 +35,29 @@ var ( // dbinfo defines the property that holds the db version. const dbinfo = "_proposals.db_" -// ProposalDB defines the common data needed to query the proposals db. -type ProposalDB struct { - lastSync int64 // atomic - dbP *storm.DB - client *http.Client - APIURLpath string +// ProposalsDB defines the object that interacts with the local proposals +// db, and with decred's politeia server. +type ProposalsDB struct { + lastSync int64 // atomic + dbP *storm.DB + client *piclient.Client + APIPath string } -// NewProposalsDB opens an exiting database or creates a new DB instance with -// the provided file name. Returns an initialized instance of proposals DB, http -// client and the formatted politeia API URL path to be used. It also checks the -// db version, Reindexes the db if need be and sets the required db version. -func NewProposalsDB(politeiaURL, dbPath string) (*ProposalDB, error) { +func NewProposalsDB(politeiaURL, dbPath string) (*ProposalsDB, error) { + // Validate arguments if politeiaURL == "" { - return nil, fmt.Errorf("missing politeia API URL") + return nil, fmt.Errorf("missing Politeia URL") } - if dbPath == "" { return nil, fmt.Errorf("missing db path") } + // Check path and open storm DB _, err := os.Stat(dbPath) if err != nil && !os.IsNotExist(err) { return nil, err } - db, err := storm.Open(dbPath) if err != nil { return nil, err @@ -70,13 +66,13 @@ func NewProposalsDB(politeiaURL, dbPath string) (*ProposalDB, error) { // Checks if the correct db version has been set. var version string err = db.Get(dbinfo, "version", &version) - if err != nil && err != storm.ErrNotFound { + if err != nil && !errors.Is(err, storm.ErrNotFound) { return nil, err } if version != dbVersion.String() { - // Attempt to delete the ProposalInfo bucket. - if err = db.Drop(&pitypes.ProposalInfo{}); err != nil { + // Attempt to delete the ProposalRecord bucket. + if err = db.Drop(&pitypes.ProposalRecord{}); err != nil { // If error due bucket not found was returned, ignore it. if !strings.Contains(err.Error(), "not found") { return nil, fmt.Errorf("delete bucket struct failed: %v", err) @@ -91,30 +87,22 @@ func NewProposalsDB(politeiaURL, dbPath string) (*ProposalDB, error) { log.Infof("proposals.db version %v was set", dbVersion) } - // Create the http client used to query the API endpoints. - c := &http.Client{ - Transport: &http.Transport{ - MaxIdleConns: 10, - IdleConnTimeout: 5 * time.Second, - DisableCompression: false, - }, - Timeout: 30 * time.Second, + pc, err := piclient.New(politeiaURL+"/api", piclient.Opts{}) + if err != nil { + return nil, err } - // politeiaURL should just be the domain part of the url without the API versioning. - versionedPath := fmt.Sprintf("%s/api/v%d", politeiaURL, piapi.PoliteiaWWWAPIVersion) - - proposalDB := &ProposalDB{ - dbP: db, - client: c, - APIURLpath: versionedPath, + proposalDB := &ProposalsDB{ + dbP: db, + client: pc, + APIPath: politeiaURL, } return proposalDB, nil } -// Close closes the proposal DB instance created passed if it not nil. -func (db *ProposalDB) Close() error { +// Close closes the proposal DB instance. +func (db *ProposalsDB) Close() error { if db == nil || db.dbP == nil { return nil } @@ -122,342 +110,486 @@ func (db *ProposalDB) Close() error { return db.dbP.Close() } -// generateCustomID generates a custom ID that is used to reference the proposals -// from the frontend. The ID generated from the title by having all its -// punctuation marks replaced with a hyphen and the string converted to lowercase. -// According to Politeia, a proposal title has a max length of 80 characters thus -// the new ID should have a max length of 80 characters. -func generateCustomID(title string) (string, error) { - if title == "" { - return "", fmt.Errorf("ID not generated: invalid title found") - } - // regex selects only the alphanumeric characters. - reg, err := regexp.Compile("[^a-zA-Z0-9]+") - if err != nil { - return "", err - } - - // Replace all punctuation marks with a hyphen and make it lower case. - return reg.ReplaceAllString(strings.ToLower(title), "-"), nil +// ProposalsLastSync reads the last sync timestamp from the atomic db. +// +// Satisfies the PoliteiaBackend interface. +func (db *ProposalsDB) ProposalsLastSync() int64 { + return atomic.LoadInt64(&db.lastSync) } -// fetchAPIData returns the API data fetched from the Politeia API endpoints. -// NB: "/api/v1/proposals/vetted" path returns the latest snapshot of the API -// data that currently exits. This implies that parameter "after=" should be used -// when syncing the data from scratch and "before=" should be used to fetch newer -// updates. -func (db *ProposalDB) fetchAPIData(URLParams string) (pitypes.Proposals, error) { - copyURLParams := URLParams - pageSize := int(piapi.ProposalListPageSize) - var publicProposals pitypes.Proposals - - // It helps determine when fresh sync is to run when no previous data - // existed. copyURLParams is an empty string when fresh sync is to run. - var param = "before" - if copyURLParams == "" { - param = "after" - } - - // Since Politeia sets page the limit as piapi.ProposalListPageSize, keep - // fetching the proposals till the count of fetched proposals is less than - // piapi.ProposalListPageSize. - for { - data, err := piclient.RetrieveAllProposals(db.client, db.APIURLpath, copyURLParams) - if err != nil { - return publicProposals, err - } - - // Break if no valid data was found. - if data == nil || data.Data == nil { - // Should help detect when API changes are effected on Politeia's end. - log.Warn("invalid or empty data entries were returned") - break - } - - if len(data.Data) == 0 { - // No updates found. - break - } - - publicProposals.Data = append(publicProposals.Data, data.Data...) - - // Break the loop when number the proposals returned are not equal to - // piapi.ProposalListPageSize in count. - if len(data.Data) != pageSize { - break - } - - copyURLParams = fmt.Sprintf("?%v=%v", param, data.Data[pageSize-1].TokenVal) +// ProposalsSync is responsible for keeping an up-to-date database synced +// with politeia's latest updates. +// +// Satisfies the PoliteiaBackend interface. +func (db *ProposalsDB) ProposalsSync() error { + // Sanity check + if db == nil || db.dbP == nil { + return errDef } - return publicProposals, nil -} - -// saveProposals adds the proposals data to the db. -func (db *ProposalDB) saveProposals(publicProposals pitypes.Proposals) (int, error) { - var proposalsSaved int - // Attempt to save a given a given item for a max of 5 times. - const maxLoop = 5 - - // Save all the proposals - for i, val := range publicProposals.Data { - var err error - if val.RefID, err = generateCustomID(val.Name); err != nil { - return 0, err - } - err = db.dbP.Save(val) - - // When a duplicate CensorshipRecord struct is detected this "already exists" - // error is thrown, this means that some edits were made to an older version - // of the proposal and its fixed by updating the new changes. In another - // case that is more rare, is that the current proposal could have a Name - // that generates a RefID similar to one already in the db and appending - // integers to it till it becomes unique is the solution. - if err == storm.ErrAlreadyExists { - var data *pitypes.ProposalInfo - // Check if the proposal token already exists in the db. - data, err = db.proposal("TokenVal", val.TokenVal) - if err == nil && data != nil { - // The proposal token already exists thus trigger an update with - // the latest details. - valCopy := *val - valCopy.ID = data.ID - suffixStr := "" - - for k := 1; k <= maxLoop; k++ { - valCopy.RefID += suffixStr - // Attempt to update the old entry. - err = db.dbP.Update(&valCopy) - if err == storm.ErrAlreadyExists { - suffixStr = strconv.Itoa(k) - continue - } - if err != nil { - log.Error("storm DB update failed: %v", err) - } - break - } - } + // Save the timestamp of the last update check. + defer atomic.StoreInt64(&db.lastSync, time.Now().UTC().Unix()) - // First try wasn't successful if err != nil. - if err != nil { - for c := 1; c <= maxLoop; c++ { - // Drop the previously assigned ID. - val.ID = 0 - - val.RefID += strconv.Itoa(c) - // Attempt to save a new entry. - err = db.dbP.Save(val) - if err == storm.ErrAlreadyExists { - continue - } - if err != nil { - log.Error("storm DB save failed: %v", err) - } - break - } - } - } + // Update db with any new proposals on politeia server. + err := db.proposalsNewUpdate() + if err != nil { + return err + } - if err != nil { - return i, fmt.Errorf("save operation failed: %v", err) - } + // Update all current proposals who might still be suffering changes + // with edits, and that has undergone some data change. + err = db.proposalsInProgressUpdate() + if err != nil { + return err + } - // increment since the save is successful. - proposalsSaved++ + // Update vote results data on finished proposals that are not yet + // fully synced with politeia. + err = db.proposalsVoteResultsUpdate() + if err != nil { + return err } - return proposalsSaved, nil + log.Info("Politeia records were synced.") + + return nil } -// AllProposals fetches all the proposals data saved to the db. -func (db *ProposalDB) AllProposals(offset, rowsCount int, - filterByVoteStatus ...int) (proposals []*pitypes.ProposalInfo, - totalCount int, err error) { +// ProposalsAll fetches the proposals data from the local db. +// The argument filterByVoteStatus is optional. +// +// Satisfies the PoliteiaBackend interface. +func (db *ProposalsDB) ProposalsAll(offset, rowsCount int, + filterByVoteStatus ...int) ([]*pitypes.ProposalRecord, int, error) { + // Sanity check if db == nil || db.dbP == nil { return nil, 0, errDef } var query storm.Query + if len(filterByVoteStatus) > 0 { - // Filter by the votes status query = db.dbP.Select(q.Eq("VoteStatus", - pitypes.VoteStatusType(filterByVoteStatus[0]))) + ticketvotev1.VoteStatusT(filterByVoteStatus[0]))) } else { query = db.dbP.Select() } // Count the proposals based on the query created above. - totalCount, err = query.Count(&pitypes.ProposalInfo{}) + totalCount, err := query.Count(&pitypes.ProposalRecord{}) if err != nil { - return + return nil, 0, err } // Return the proposals listing starting with the newest. + var proposals []*pitypes.ProposalRecord err = query.Skip(offset).Limit(rowsCount).Reverse().OrderBy("Timestamp"). Find(&proposals) - if err != nil && err != storm.ErrNotFound { + if err != nil && !errors.Is(err, storm.ErrNotFound) { log.Errorf("Failed to fetch data from Proposals DB: %v", err) - } else { - err = nil } - return + return proposals, totalCount, nil } -// ProposalByToken returns the single proposal identified by the provided token. -func (db *ProposalDB) ProposalByToken(proposalToken string) (*pitypes.ProposalInfo, error) { +// ProposalByToken retrieves the proposal for the given token argument. +// +// Satisfies the PoliteiaBackend interface. +func (db *ProposalsDB) ProposalByToken(token string) (*pitypes.ProposalRecord, error) { if db == nil || db.dbP == nil { return nil, errDef } - return db.proposal("TokenVal", proposalToken) + return db.proposal("Token", token) } -// ProposalByRefID returns the single proposal identified by the provided refID. -// RefID is generated from the proposal name and used as the descriptive part of -// the URL to proposal details page on the /proposal page. -func (db *ProposalDB) ProposalByRefID(RefID string) (*pitypes.ProposalInfo, error) { - if db == nil || db.dbP == nil { - return nil, errDef +// fetchVettedTokens fetches all vetted tokens ordered by the timestamp of +// their last status change. +func (db *ProposalsDB) fetchVettedTokensInventory() ([]string, error) { + page := 0 + vettedTokens := []string{} + for { + inventoryReq := recordsv1.InventoryOrdered{ + State: recordsv1.RecordStateVetted, + Page: uint32(page + 1), + } + reply, err := db.client.RecordInventoryOrdered(inventoryReq) + if err != nil { + return nil, fmt.Errorf("Pi client RecordInventoryOrdered err: %v", + err) + } + + vettedTokens = append(vettedTokens, reply.Tokens...) + + // Break loop if we fetch last page + if len(reply.Tokens) < int(recordsv1.InventoryPageSize) { + break + } + } + return vettedTokens, nil +} + +// fetchRecordDetails fetches the record details of the given proposal tokens. +func (db *ProposalsDB) fetchRecordDetails(tokens []string) (map[string]recordsv1.Record, error) { + records := make(map[string]recordsv1.Record, len(tokens)) + for _, token := range tokens { + detailsReq := recordsv1.Details{ + Token: token, + } + dr, err := db.client.RecordDetails(detailsReq) + if err != nil { + return nil, fmt.Errorf("Pi client RecordDetails err: %v", err) + } + records[token] = *dr } - return db.proposal("RefID", RefID) + return records, nil } -// proposal runs the query with searchBy and searchTerm parameters provided and -// returns the result. -func (db *ProposalDB) proposal(searchBy, searchTerm string) (*pitypes.ProposalInfo, error) { - var pInfo pitypes.ProposalInfo - err := db.dbP.Select(q.Eq(searchBy, searchTerm)).Limit(1).First(&pInfo) +// fetchProposalsData returns the parsed vetted proposals from politeia +// API's. It cooks up the data needed to save the proposals in stormdb. It +// first fetches the proposal details, then comments and then vote summary. +// This data is needed for the information provided in the dcrdata UI. The +// data returned does not include ticket vote data. +func (db *ProposalsDB) fetchProposalsData(tokens []string) ([]*pitypes.ProposalRecord, error) { + // Fetch record details for each token from the inventory + recordDetails, err := db.fetchRecordDetails(tokens) if err != nil { - if !errors.Is(err, storm.ErrNotFound) { - log.Errorf("Failed to fetch data from Proposals DB: %v", err) - } return nil, err } - return &pInfo, nil -} + // Fetch comments count for each token from the inventory + cr, err := db.client.CommentCount(commentsv1.Count{ + Tokens: tokens, + }) + if err != nil { + return nil, fmt.Errorf("Pi client CommentCount err: %v", err) + } + commentsCounts := cr.Counts -// LastProposalsSync returns the last time a sync to update the proposals was run -// but not necessarily the last time updates were synced in proposals.db. -func (db *ProposalDB) LastProposalsSync() int64 { - return atomic.LoadInt64(&db.lastSync) -} + // Fetch vote summary for each token from the inventory + sr, err := db.client.TicketVoteSummaries(ticketvotev1.Summaries{ + Tokens: tokens, + }) + if err != nil { + return nil, fmt.Errorf("Pi client TicketVoteSummaries err: %v", err) + } + voteSummaries := sr.Summaries -// CheckProposalsUpdates updates the proposal changes if they exist and updates -// them to the proposal db. -func (db *ProposalDB) CheckProposalsUpdates() error { - if db == nil || db.dbP == nil { - return errDef + var proposals []*pitypes.ProposalRecord + + // Iterate through every record and feed data used by dcrdata + for _, record := range recordDetails { + proposal := pitypes.ProposalRecord{} + + // Record data + proposal.State = record.State + proposal.Status = record.Status + proposal.Version = record.Version + proposal.Timestamp = uint64(record.Timestamp) + proposal.Username = record.Username + proposal.Token = record.CensorshipRecord.Token + + // Proposal metadata + pm, err := proposalMetadataDecode(record.Files) + if err != nil { + return nil, fmt.Errorf("proposalMetadataDecode err: %v", err) + } + proposal.Name = pm.Name + + // User metadata + um, err := userMetadataDecode(record.Metadata) + if err != nil { + return nil, fmt.Errorf("userMetadataDecode err: %v", err) + } + proposal.UserID = um.UserID + + // Comments count + proposal.CommentsCount = + int32(commentsCounts[record.CensorshipRecord.Token]) + + // Vote summary data + summary := voteSummaries[proposal.Token] + proposal.VoteStatus = summary.Status + proposal.VoteResults = summary.Results + proposal.EligibleTickets = summary.EligibleTickets + proposal.StartBlockHeight = summary.StartBlockHeight + proposal.EndBlockHeight = summary.EndBlockHeight + proposal.QuorumPercentage = summary.QuorumPercentage + proposal.PassPercentage = summary.PassPercentage + + var totalVotes uint64 + for _, v := range summary.Results { + totalVotes += v.Votes + } + proposal.TotalVotes = totalVotes + + // Status change metadata + ts, changeMsg, err := statusChangeMetadataDecode(record.Metadata) + if err != nil { + return nil, fmt.Errorf("statusChangeMetadataDecode err: %v", err) + } + proposal.PublishedAt = ts[0] + proposal.CensoredAt = ts[1] + proposal.AbandonedAt = ts[2] + proposal.StatusChangeMsg = changeMsg + + // Append proposal after inserting the relevant data + proposals = append(proposals, &proposal) } - defer atomic.StoreInt64(&db.lastSync, time.Now().UTC().Unix()) + return proposals, nil +} - // Retrieve and update all current proposals whose vote statuses is either - // NotAuthorized, Authorized and Started - numRecords, err := db.updateInProgressProposals() +func (db *ProposalsDB) fetchTicketVoteResults(token string) (*pitypes.ProposalChartData, error) { + // Fetch ticket votes details to acquire vote bits options info. + details, err := db.client.TicketVoteDetails(ticketvotev1.Details{ + Token: token, + }) if err != nil { - return err + return nil, fmt.Errorf("Pi client TicketVoteDetails err: %v", err) } - // Retrieve and update any new proposals created since the previous - // proposals were stored in the db. - lastProposal, err := db.lastSavedProposal() - if err != nil && err != storm.ErrNotFound { - return fmt.Errorf("lastSavedProposal failed: %v", err) + // Maps the vote bits option to their respective string ID. + voteOptsMap := make(map[uint64]string) + for _, opt := range details.Vote.Params.Options { + voteOptsMap[opt.Bit] = opt.ID } - var queryParam string - if len(lastProposal) > 0 && lastProposal[0].TokenVal != "" { - queryParam = fmt.Sprintf("?before=%s", lastProposal[0].TokenVal) - } - publicProposals, err := db.fetchAPIData(queryParam) + tvr, err := db.client.TicketVoteResults(ticketvotev1.Results{ + Token: token, + }) if err != nil { - return err + return nil, fmt.Errorf("Pi client TicketVoteResults err: %v", err) } - n, err := db.saveProposals(publicProposals) - if err != nil { - return err + // Parse reply to proposal chart data + var chart pitypes.ProposalChartData + var timestamps []int64 + for _, v := range tvr.Votes { + bit, err := strconv.ParseUint(v.VoteBit, 16, 64) + if err != nil { + return nil, err + } + switch voteOptsMap[bit] { + case "yes": + chart.Yes = append(chart.Yes, 1) + chart.No = append(chart.No, 0) + case "no": + chart.No = append(chart.No, 1) + chart.Yes = append(chart.Yes, 0) + } + timestamps = append(timestamps, v.Timestamp) } + sort.Slice(timestamps, func(i, j int) bool { + return timestamps[i] < timestamps[j] + }) + chart.Time = timestamps - // Add the sum of the newly added proposals. - numRecords += n + return &chart, nil +} - log.Infof("%d politeia proposal DB records were updated", numRecords) +// proposalsSave saves the proposals data to the db. +func (db *ProposalsDB) proposalsSave(proposals []*pitypes.ProposalRecord) error { + for _, proposal := range proposals { + proposal.Synced = false + err := db.dbP.Save(proposal) + if errors.Is(err, storm.ErrAlreadyExists) { + // Proposal exists, update instead of inserting new + data, err := db.ProposalByToken(proposal.Token) + if err != nil { + return fmt.Errorf("ProposalsDB ProposalByToken err: %v", err) + } + updateData := *proposal + updateData.ID = data.ID + err = db.dbP.Update(&updateData) + if err != nil { + return fmt.Errorf("stormdb update err: %v", err) + } + } + if err != nil { + return fmt.Errorf("stormdb save err: %v", err) + } + } return nil } -func (db *ProposalDB) lastSavedProposal() (lastP []*pitypes.ProposalInfo, err error) { - err = db.dbP.Select().Limit(1).OrderBy("Timestamp").Reverse().Find(&lastP) - return +// proposal is used to retrieve proposals from stormdb given the search +// arguments passed in. +func (db *ProposalsDB) proposal(searchBy, searchTerm string) (*pitypes.ProposalRecord, error) { + var proposal pitypes.ProposalRecord + err := db.dbP.Select(q.Eq(searchBy, searchTerm)).Limit(1).First(&proposal) + if err != nil { + log.Errorf("Failed to fetch data from Proposals DB: %v", err) + return nil, err + } + + return &proposal, nil } -// Proposals whose vote statuses are either NotAuthorized, Authorized or Started -// are considered to be in progress. Data for the in progress proposals is -// fetched from Politeia API. From the newly fetched proposals data, db update -// is only made for the vote statuses without NotAuthorized status out of all -// the new votes statuses fetched. -func (db *ProposalDB) updateInProgressProposals() (int, error) { - // statuses defines a list of vote statuses whose proposals may need an update. - statuses := []pitypes.VoteStatusType{ - pitypes.VoteStatusType(piapi.PropVoteStatusNotAuthorized), - pitypes.VoteStatusType(piapi.PropVoteStatusAuthorized), - pitypes.VoteStatusType(piapi.PropVoteStatusStarted), +// proposalsNewUpdate verifies if there is any new proposals on the politeia +// server that are not yet synced with our stormdb. +func (db *ProposalsDB) proposalsNewUpdate() error { + var proposals []*pitypes.ProposalRecord + err := db.dbP.All(&proposals) + if err != nil { + return fmt.Errorf("stormdb All err: %v", err) + } + + var tokens []string + if len(proposals) == 0 { + // Empty db so first time fetching proposals, fetch all vetted tokens + vettedTokens, err := db.fetchVettedTokensInventory() + if err != nil { + return err + } + tokens = vettedTokens + } else { + // Fetch inventory to search for new proposals + inventoryReq := recordsv1.InventoryOrdered{ + State: recordsv1.RecordStateVetted, + Page: 1, + } + reply, err := db.client.RecordInventoryOrdered(inventoryReq) + if err != nil { + return fmt.Errorf("Pi client RecordInventoryOrdered err: %v", + err) + } + + // Create proposals map from local stormdb proposals + proposalsMap := make(map[string]*pitypes.ProposalRecord, len(proposals)) + for _, prop := range proposals { + proposalsMap[prop.Token] = prop + } + + // Filter new proposals to be fetched + var tokensProposalsNew []string + for _, token := range reply.Tokens { + if _, ok := proposalsMap[token]; ok { + continue + } + // New proposal found + tokensProposalsNew = append(tokensProposalsNew, token) + } + tokens = tokensProposalsNew + } + + // Fetch data for found tokens + var prs []*pitypes.ProposalRecord + if len(tokens) > 0 { + prs, err = db.fetchProposalsData(tokens) + if err != nil { + return err + } + } + + // Save proposals data on stormdb + if len(prs) > 0 { + err = db.proposalsSave(prs) + if err != nil { + return err + } } - var inProgress []*pitypes.ProposalInfo + return nil +} + +// proposalsInProgressUpdate retrieves proposals with the vote status equal to +// unauthorized, authorized and started. Afterwords, it proceeds to check with +// newly fetched data if any of them need to be updated on stormdb. +func (db *ProposalsDB) proposalsInProgressUpdate() error { + var propsInProgress []*pitypes.ProposalRecord err := db.dbP.Select( q.Or( - q.Eq("VoteStatus", statuses[0]), - q.Eq("VoteStatus", statuses[1]), - q.Eq("VoteStatus", statuses[2]), + q.Eq("VoteStatus", ticketvotev1.VoteStatusUnauthorized), + q.Eq("VoteStatus", ticketvotev1.VoteStatusAuthorized), + q.Eq("VoteStatus", ticketvotev1.VoteStatusStarted), ), - ).Find(&inProgress) - // Return an error only if the said error is not 'not found' error. - if err != nil && err != storm.ErrNotFound { - return 0, err + ).Find(&propsInProgress) + if err != nil && !errors.Is(err, storm.ErrNotFound) { + return err } - // count defines the number of total updated records. - var count int - - for _, val := range inProgress { - proposal, err := piclient.RetrieveProposalByToken(db.client, db.APIURLpath, val.TokenVal) - // Do not update if: - // 1. piclient.RetrieveProposalByToken returned an error + for _, prop := range propsInProgress { + proposals, err := db.fetchProposalsData([]string{prop.Token}) if err != nil { - // Since the proposal tokens being updated here are already in the - // proposals.db. Do not return errors found since they will still be - // updated when the data is available. - log.Errorf("RetrieveProposalByToken failed: %v ", err) - continue + return fmt.Errorf("fetchProposalsData failed with err: %s", err) + } + proposal := proposals[0] + + // Ticket vote results is an expensive API call, so we check + // appropriate conditions to call it. Vote status needs to be started + // for in progress proposals. Then we check the total votes to see + // if any new votes has been cast. Then we check if chart data is nil, + // which means first time fetching ticket vote data. + if prop.VoteStatus == ticketvotev1.VoteStatusStarted && + (prop.TotalVotes != proposal.TotalVotes || prop.ChartData == nil) { + voteResults, err := db.fetchTicketVoteResults(prop.Token) + if err != nil { + return fmt.Errorf("fetchTicketVoteResults failed with err: %s", err) + } + proposal.ChartData = voteResults } - proposal.Data.ID = val.ID - proposal.Data.RefID = val.RefID - - // 2. The new proposal data has not changed. - if val.IsEqual(proposal.Data) { + if prop.IsEqual(*proposal) { + // No changes made to proposal, skip db call. continue } - // 4. Some or all data returned was empty or invalid. - if proposal.Data.TokenVal == "" || proposal.Data.TotalVotes < val.TotalVotes { - // Should help detect when API changes are effected on Politeia's end. - log.Warnf("invalid or empty data entries were returned for %v", val.TokenVal) - continue + // Insert ID from storm DB to update proposal. + proposal.ID = prop.ID + + err = db.dbP.Update(proposal) + if err != nil { + return fmt.Errorf("storm db Update failed with err: %s", err) } + } + + return nil +} - err = db.dbP.Update(proposal.Data) +// proposalsVoteResultsUpdate verifies if there is still a need to update vote +// results data for proposals with the vote status equal to finished, approved +// and rejected. This is the final sync between dcrdata and politeia servers +// for proposals with the final finished/approved/rejected vote status. +func (db *ProposalsDB) proposalsVoteResultsUpdate() error { + // Get proposals that need to be synced + var propsVotingComplete []*pitypes.ProposalRecord + err := db.dbP.Select( + q.Or( + q.And( + q.Eq("VoteStatus", ticketvotev1.VoteStatusFinished), + q.Eq("Synced", false), + ), + q.And( + q.Eq("VoteStatus", ticketvotev1.VoteStatusApproved), + q.Eq("Synced", false), + ), q.And( + q.Eq("VoteStatus", ticketvotev1.VoteStatusRejected), + q.Eq("Synced", false), + ), + ), + ).Find(&propsVotingComplete) + if err != nil && !errors.Is(err, storm.ErrNotFound) { + return err + } + + // Update finished proposals that are not yet synced with the + // latest vote results. + for _, prop := range propsVotingComplete { + voteResults, err := db.fetchTicketVoteResults(prop.Token) if err != nil { - return 0, fmt.Errorf("Update for %s failed with error: %v ", val.TokenVal, err) + return fmt.Errorf("fetchTicketVoteResults failed with err: %s", err) } + prop.ChartData = voteResults + prop.Synced = true - count++ + err = db.dbP.Update(prop) + if err != nil { + return fmt.Errorf("storm db Update failed with err: %s", err) + } } - return count, nil + + return nil } diff --git a/gov/politeia/proposals_test.go b/gov/politeia/proposals_test.go deleted file mode 100644 index 8d6f4bc94..000000000 --- a/gov/politeia/proposals_test.go +++ /dev/null @@ -1,571 +0,0 @@ -package politeia - -import ( - "fmt" - "io/ioutil" - "net/http" - "net/http/httptest" - "os" - "path/filepath" - "reflect" - "strconv" - "testing" - - "github.com/asdine/storm/v3" - "github.com/decred/dcrdata/gov/v4/politeia/types" - pitypes "github.com/decred/dcrdata/gov/v4/politeia/types" - piapi "github.com/decred/politeia/politeiawww/api/www/v1" -) - -var db *storm.DB -var tempDir string - -// initial sample proposal made. -var firstProposal = &pitypes.ProposalInfo{ - Name: "Initial Test proposal", - RefID: "initial-test-proposal", - State: 2, - Status: 4, - Timestamp: 1541904469, - UserID: "18b24b6c-14a8-45f6-ab2e-a34127840fb3", - Username: "secret-coder", - PublicKey: "c7580e9d13a21a2046557f7ef0148a5be89fbe8db8c", - Signature: "8a1b69eb08b413b3ad3161c9b43b6a65a25c537f6151866d391a352", - Version: "6", - CensorshipRecord: pitypes.CensorshipRecord{ - TokenVal: "0aaab331075d08cb03333d5a1bef04b99a708dcbfebc8f8c94040ceb1676e684", - MerkleRoot: "cfaf772010b439db2fa175b407f7c61fc7b06fbd844192a89551abe40791b6bb", - Signature: "6f8a7740c518972c4dc607e877afc794be9f99a1c4790837a7104b7eb6228d4db219", - }, - NumComments: 23, - PublishedDate: 1541904469, - AbandonedDate: 1543946266, -} - -// TestMain sets up the temporary db needed for testing -func TestMain(m *testing.M) { - var err error - tempDir, err = ioutil.TempDir(os.TempDir(), "offchain") - if err != nil { - panic(err) - } - - db, err = storm.Open(filepath.Join(tempDir, "test.db")) - if err != nil { - panic(err) - } - - // Save the first sample proposal - err = db.Save(firstProposal) - if err != nil { - panic(err) - } - - returnVal := m.Run() - - defer db.Close() - defer os.RemoveAll(tempDir) // clean up - - os.Exit(returnVal) -} - -// TestNewProposalsDB tests creating a new storm db and a http client instance. -func TestNewProposalsDB(t *testing.T) { - var count int - inputURLPath := "https://proposals.decred.org" - expectedPath := "https://proposals.decred.org/api/v1" - getDbPath := func() string { - count++ - return filepath.Join(tempDir, fmt.Sprintf("test%v.db", count)) - } - - type testData struct { - politeiaAPIURL string - dbPath string - - // Checks if the db was created and its instance referenced returned. - IsdbInstance bool - errMsg string - } - - td := []testData{ - { - politeiaAPIURL: "", - dbPath: "", - IsdbInstance: false, - errMsg: "missing politeia API URL", - }, - { - politeiaAPIURL: inputURLPath, - dbPath: "", - IsdbInstance: false, - errMsg: "missing db path", - }, - { - politeiaAPIURL: "", - dbPath: getDbPath(), - IsdbInstance: false, - errMsg: "missing politeia API URL", - }, - { - politeiaAPIURL: inputURLPath, - dbPath: getDbPath(), - IsdbInstance: true, - errMsg: "", - }, - } - - for i, data := range td { - t.Run("Test_#"+strconv.Itoa(i), func(t *testing.T) { - result, err := NewProposalsDB(data.politeiaAPIURL, data.dbPath) - - var expectedErrMsg string - if err != nil { - expectedErrMsg = err.Error() - } - - if expectedErrMsg != data.errMsg { - t.Fatalf("expected to find error '%v' but found '%v'", data.errMsg, err) - } - - if data.IsdbInstance && result != nil { - if result.APIURLpath != expectedPath { - t.Fatalf("expected the API URL to '%v' but found '%v'", result.APIURLpath, expectedPath) - } - - if result.client == nil { - t.Fatal("expected the http client not to be nil but was nil") - } - - if result.dbP == nil { - t.Fatal("expected the db instance not to be nil but was nil") - } - } else if result != nil { - // The result should be nil since the incorrect inputs resulted - // to an error being returned and a nil proposalDB instance. - t.Fatalf("expect the returned result to be nil but was not nil") - } - - // expects to find the correspnding db at the given path. - if data.IsdbInstance { - if _, err := os.Stat(data.dbPath); os.IsNotExist(err) { - t.Fatalf("expected to find the corresponding db at '%v' path but did not.", data.dbPath) - } - } - }) - } -} - -// mockServer mocks helps avoid making actual http calls during tests. It payloads -// in the same format as would be returned by the normal API endpoint. -func mockServer() *httptest.Server { - return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - var resp string - switch r.URL.Path { - case piapi.RouteAllVetted: - resp = `{ - "proposals":[ - { - "name":"Change language: PoS Mining to PoS Voting, Stakepool to Voting Service Provider", - "state":2, - "status":4, - "timestamp":1539880429, - "userid":"350a4b6c-5cdd-4d87-822a-4900dc3a930c", - "username":"richard-red", - "publickey":"cd6e57b93f95dd0386d670c7ce42cb0ccd1cd5b997e87a716e9359e20251994e", - "signature":"c0e3285d447fd2acf1f2e1a0c86a71383dfe71b1b01e0068e56e8e7649dadb7aa503a5f99765fc3a24da8716fd5b89f75bb97762e756f15303e96d135a2e7109", - "files":[ - - ], - "numcomments":19, - "version":"1", - "publishedat":1539898457, - "censorshiprecord":{ - "token":"522652954ea7998f3fca95b9c4ca8907820eb785877dcf7fba92307131818c75", - "merkle":"20c9234c50e0dc78d28003fd57995192a16ca73349f5d97be456128984e463fc", - "signature":"d1d44788cdf8d838aad97aa829b2f27f8a32897010d6373c9d3ca1a42820dcafe2615c1904558c6628c5f9165691ead087c0cb2ada023b9aa3f76b6c587ac90e" - } - } - ] - }` - case piapi.RouteAllVoteStatus: - resp = `{ - "votesstatus":[ - { - "token":"522652954ea7998f3fca95b9c4ca8907820eb785877dcf7fba92307131818c75", - "status":4, - "totalvotes":12745, - "optionsresult":[ - { - "option":{ - "id":"no", - "description":"Don't approve proposal", - "bits":1 - }, - "votesreceived":754 - }, - { - "option":{ - "id":"yes", - "description":"Approve proposal", - "bits":2 - }, - "votesreceived":11991 - } - ], - "endheight":"289500", - "numofeligiblevotes":40958, - "quorumpercentage":20, - "passpercentage":60 - } - ] - }` - } - w.Write([]byte(resp)) - })) -} - -// mockedPayload defines the complete unmarshalled sing payload returned by the -// mocked handleGetRequests. -var mockedPayload = &pitypes.ProposalInfo{ - ID: 2, - Name: "Change language: PoS Mining to PoS Voting, Stakepool to Voting Service Provider", - RefID: "change-language-pos-mining-to-pos-voting-stakepool-to-voting-service-provider", - State: 2, - Status: 4, - Timestamp: 1539880429, - UserID: "350a4b6c-5cdd-4d87-822a-4900dc3a930c", - Username: "richard-red", - PublicKey: "cd6e57b93f95dd0386d670c7ce42cb0ccd1cd5b997e87a716e9359e20251994e", - Signature: "c0e3285d447fd2acf1f2e1a0c86a71383dfe71b1b01e0068e56e8e7649dadb7aa503a5f99765fc3a24da8716fd5b89f75bb97762e756f15303e96d135a2e7109", - NumComments: 19, - // Files: []pitypes.AttachmentFile{}, - Version: "1", - PublishedDate: 1539898457, - CensorshipRecord: pitypes.CensorshipRecord{ - TokenVal: "522652954ea7998f3fca95b9c4ca8907820eb785877dcf7fba92307131818c75", - MerkleRoot: "20c9234c50e0dc78d28003fd57995192a16ca73349f5d97be456128984e463fc", - Signature: "d1d44788cdf8d838aad97aa829b2f27f8a32897010d6373c9d3ca1a42820dcafe2615c1904558c6628c5f9165691ead087c0cb2ada023b9aa3f76b6c587ac90e", - }, - ProposalVotes: pitypes.ProposalVotes{ - Token: "522652954ea7998f3fca95b9c4ca8907820eb785877dcf7fba92307131818c75", - VoteStatus: 4, - TotalVotes: 12745, - VoteResults: []pitypes.Results{ - { - Option: pitypes.VoteOption{ - OptionID: "no", - Description: "Don't approve proposal", - Bits: 1, - }, - VotesReceived: 754, - }, - { - Option: pitypes.VoteOption{ - OptionID: "yes", - Description: "Approve proposal", - Bits: 2, - }, - VotesReceived: 11991, - }, - }, - Endheight: "289500", - NumOfEligibleVotes: 40958, - QuorumPercentage: 20, - PassPercentage: 60, - }, -} - -// TestStuff tests the update functionality, all proposals retrieval and -// proposal Retrieval by ID. -func TestStuff(t *testing.T) { - server := mockServer() - newDBInstance := &ProposalDB{ - dbP: db, - client: server.Client(), - APIURLpath: server.URL, - } - - defer server.Close() - - // Testing the update functionality - t.Run("Test_CheckProposalsUpdates", func(t *testing.T) { - err := newDBInstance.CheckProposalsUpdates() - if err != nil { - t.Fatalf("expected no error to be returned but found '%v'", err) - } - }) - - // Testing the retrieval of all proposals - t.Run("Test_AllProposals", func(t *testing.T) { - offset := 0 - limit := 10 - proposals, count, err := newDBInstance.AllProposals(offset, limit) - if err != nil { - t.Fatal(err) - } - - if len(proposals) != 2 { - t.Fatalf("expected to find two proposals but found %d", len(proposals)) - } - - if count != 2 { - t.Fatalf("expected to find count equal to 2 but found %d", count) - } - - for _, data := range proposals { - if data == nil { - t.Fatal("expected the proposal not to be nil but was nil") - } - - switch data.TokenVal { - case firstProposal.TokenVal: - if !reflect.DeepEqual(data, firstProposal) { - t.Fatal("expected the initialProposal to match the retrieved but it did not") - } - - case mockedPayload.TokenVal: - if !reflect.DeepEqual(data, mockedPayload) { - t.Fatal("expected the Second Proposal to match the retrieved but it did not") - } - - default: - t.Fatal("unknown incorrect data returned") - } - } - }) - - // Testing proposals Retrieval by vote status - t.Run("Test_AllProposals_By_VoteStatus", func(t *testing.T) { - offset := 0 - limit := 10 - voteStatus := 4 // Status "Finished". - proposals, count, err := newDBInstance.AllProposals(offset, limit, voteStatus) - if err != nil { - t.Fatal(err) - } - - if len(proposals) != 1 { - t.Fatalf("expected to find one proposal but found %d", len(proposals)) - } - - if count != 1 { - t.Fatalf("expected to find count equal to 1 but found %d", count) - } - - if !reflect.DeepEqual(proposals[0], mockedPayload) { - t.Fatal("expected the Second Proposal to match the retrieved but it did not") - } - }) - - // Testing proposal retrieval by Token - t.Run("Test_ProposalByToken", func(t *testing.T) { - proposal, err := newDBInstance.ProposalByToken(firstProposal.TokenVal) - if err != nil { - t.Fatal(err) - } - - if !reflect.DeepEqual(proposal, firstProposal) { - t.Fatal("expected the initialProposal to match the retrieved but it did not") - } - }) - - // Testing proposal retrieval by RefID - t.Run("Test_ProposalByRefID", func(t *testing.T) { - proposal, err := newDBInstance.ProposalByRefID("initial-test-proposal") - if err != nil { - t.Fatal(err) - } - - if !reflect.DeepEqual(proposal, firstProposal) { - t.Fatal("expected the initialProposal to match the retrieved but it did not") - } - }) -} - -func TestGenerateCustomID(t *testing.T) { - type testData struct { - title string - customID string - isError bool - } - - td := []testData{ - { - title: "", - customID: "", - isError: true, - }, - { - title: "Decred Bug Bounty Proposal", - customID: "decred-bug-bounty-proposal", - }, - { - title: "Smart Reach Partnership Proposal -- Jan 2019", - customID: "smart-reach-partnership-proposal-jan-2019", - }, - { - title: "Proposed Statement Of Work (SOW) For Decred Blockchain Wallet Tutorial Campaign", - customID: "proposed-statement-of-work-sow-for-decred-blockchain-wallet-tutorial-campaign", - }, - } - - for i, val := range td { - t.Run("Test_#"+strconv.Itoa(i), func(t *testing.T) { - newID, err := generateCustomID(val.title) - - if err != nil && !val.isError { - t.Fatalf("expected no error but found (%v)", err) - } - - if err == nil && val.isError { - t.Fatal("expected an error but found none") - } - - if newID != val.customID { - t.Fatalf("expected the new ID to be (%s) but found (%v)", val.customID, newID) - } - }) - } -} - -// TestSaveProposals tests the functionality of saveProposals method. -func TestSaveProposals(t *testing.T) { - newDB := &ProposalDB{dbP: db} - - copy1FirstProposal := *firstProposal - copy2FirstProposal := *firstProposal - copy1MockProposal := *mockedPayload - copy2MockProposal := *mockedPayload - - // Delete the primary Key - copy1FirstProposal.ID = 0 - copy2FirstProposal.ID = 0 - copy1MockProposal.ID = 0 - copy2MockProposal.ID = 0 - - t.Run("Test_update_proposal_if_same_tokenID_and_same_RefID_found", func(t *testing.T) { - // Should just update the old instance of timestamp value without creating a - // proposal new entry. - copy1FirstProposal.Timestamp = 1200000 - propInfo := pitypes.Proposals{Data: []*pitypes.ProposalInfo{©1FirstProposal}} - - _, err := newDB.saveProposals(propInfo) - if err != nil { - t.Fatalf("expected no error from saveProposals() but got: %v", err) - } - - newProposal, err := newDB.ProposalByToken(copy1FirstProposal.TokenVal) - if err != nil { - t.Fatalf("expected no error from ProposalByToken() but got: %v", err) - } - - if copy1FirstProposal.Name != newProposal.Name { - t.Fatalf("expected the proposal Name to be (%v) but found (%v)", - copy1FirstProposal.Name, newProposal.Name) - } - - newRefID, _ := generateCustomID(copy1FirstProposal.Name) - if newRefID != newProposal.RefID { - t.Fatalf("expected the new RefID to be (%v) but found (%v)", - newRefID, newProposal.RefID) - } - }) - - t.Run("Test_update_proposal_if_same_tokenID_and_new_RefID_found", func(t *testing.T) { - // Update the Name which will result to a new RefID. The old proposal - // details should remain but the new RefID will be updated. It should not - // create a new proposal. - copy2FirstProposal.Name = "Integrate decred with Trezor hardware wallet." - propInfo := pitypes.Proposals{Data: []*pitypes.ProposalInfo{©2FirstProposal}} - - _, err := newDB.saveProposals(propInfo) - if err != nil { - t.Fatalf("expected no error from saveProposals() but got: %v", err) - } - - newProposal, err := newDB.ProposalByToken(copy2FirstProposal.TokenVal) - if err != nil { - t.Fatalf("expected no error from ProposalByToken() but got: %v", err) - } - - if copy2FirstProposal.Name != newProposal.Name { - t.Fatalf("expected the proposal Name to be (%v) but found (%v)", - copy2FirstProposal.Name, newProposal.Name) - } - - newRefID, _ := generateCustomID(copy2FirstProposal.Name) - if newRefID != newProposal.RefID { - t.Fatalf("expected the new RefID to be (%v) but found (%v)", - newRefID, newProposal.RefID) - } - - if copy2FirstProposal.Timestamp != newProposal.Timestamp { - t.Fatalf("expected the new timestamp to be %v but found %v", - copy2FirstProposal.Timestamp, newProposal.Timestamp) - } - }) - - t.Run("Test_create_new_proposal_if_new_token_found", func(t *testing.T) { - // Updating the CensorshipRecord struct creates a new proposal thus a - // new entry should be pushed to the db. - copy1MockProposal.CensorshipRecord = types.CensorshipRecord{ - TokenVal: "censorshiprecord-edit-creates-new-proposal", - } - propInfo := pitypes.Proposals{Data: []*pitypes.ProposalInfo{©1MockProposal}} - - _, err := newDB.saveProposals(propInfo) - if err != nil { - t.Fatalf("expected no error from saveProposals() but got: %v", err) - } - - newProposal, err := newDB.ProposalByToken(copy1MockProposal.TokenVal) - if err != nil { - t.Fatalf("expected no error from ProposalByToken() but got: %v", err) - } - - if copy1MockProposal.Name != newProposal.Name { - t.Fatalf("expected the proposal Name to be (%v) but found (%v)", - copy1MockProposal.Name, newProposal.Name) - } - - newRefID, _ := generateCustomID(copy1MockProposal.Name) - if newRefID == newProposal.RefID { - t.Fatalf("expected the new RefID (%v) not to be equal to (%v) but it was", - newRefID, newProposal.RefID) - } - }) - - t.Run("Test_create_new_proposal_if_new_tokenID_and_duplicate_RefID_found", func(t *testing.T) { - // If two different proposals (different because they have unique - // censorshiprecord struct data) but share the proposal name thus - // resulting to a duplicate RefID, the duplicate RefID will be appended - // with some integers to make it unique. - copy2MockProposal.Name = "Integrate decred with Trezor hardware wallet." - copy2MockProposal.CensorshipRecord = types.CensorshipRecord{ - TokenVal: "create-trezor-wallet-integration", - } - propInfo := pitypes.Proposals{Data: []*pitypes.ProposalInfo{©2MockProposal}} - - _, err := newDB.saveProposals(propInfo) - if err != nil { - t.Fatalf("expected no error from saveProposals() but got: %v", err) - } - - newProposal, err := newDB.ProposalByToken(copy2MockProposal.TokenVal) - if err != nil { - t.Fatalf("expected no error from ProposalByToken() but got: %v", err) - } - - if copy2MockProposal.Name != newProposal.Name { - t.Fatalf("expected the proposal Name to be (%v) but found (%v)", - copy2MockProposal.Name, newProposal.Name) - } - - newRefID, _ := generateCustomID(copy2MockProposal.Name) - if newRefID == newProposal.RefID { - t.Fatalf("expected the new RefID (%v) not to be equal to (%v) but it was", - newRefID, newProposal.RefID) - } - }) -} diff --git a/gov/politeia/types/types.go b/gov/politeia/types/types.go index 72a42fb7d..20796331f 100644 --- a/gov/politeia/types/types.go +++ b/gov/politeia/types/types.go @@ -4,213 +4,72 @@ package types import ( - "strconv" - - piapi "github.com/decred/politeia/politeiawww/api/www/v1" -) - -// Politeia votes occur in 2016 block windows. -const windowSize = 2016 - -// ProposalInfo holds the proposal details as document here -// https://github.com/decred/politeia/blob/master/politeiawww/api/www/v1/api.md#user-proposals. -// It also holds the votes status details. The ID field is auto incremented by -// the db. A proposal can now be uniquely identified by the RefID value and the -// the contents on the CensorShipRecord struct. -type ProposalInfo struct { - ID int `json:"id" storm:"id,increment"` - Name string `json:"name"` - State ProposalStateType `json:"state"` - Status ProposalStatusType `json:"status"` - Timestamp uint64 `json:"timestamp"` - UserID string `json:"userid"` - Username string `json:"username"` - PublicKey string `json:"publickey"` - Signature string `json:"signature"` - Version string `json:"version"` - NumComments int32 `json:"numcomments"` - StatusChangeMsg string `json:"statuschangemessage"` - PublishedDate uint64 `json:"publishedat" storm:"index"` - CensoredDate uint64 `json:"censoredat"` - AbandonedDate uint64 `json:"abandonedat"` - // RefID was added to create an easily readable part of the URL that helps - // to reference the proposals details page. Storm db ignores entries with - // duplicate pk but returns "ErrAlreadyExists" error if the field other than - // the pk has the tag "unique". - RefID string `storm:"unique"` - // "unique" tag helps to detect when a single proposal instance wants to be - // pushed to the db as two different instances instead of one. This bug - // happened due to edits made to a proposal title thus new RefID was created. - CensorshipRecord `json:"censorshiprecord" storm:"unique"` - ProposalVotes `json:"votes"` - // Files []AttachmentFile `json:"files"` -} - -// Proposals defines an array of proposals payload as returned by RouteAllVetted route. -type Proposals struct { - Data []*ProposalInfo `json:"proposals"` -} - -// Proposal defines a proposal payload as returned by RouteProposalDetails route. -type Proposal struct { - Data *ProposalInfo `json:"proposal"` -} - -// CensorshipRecord is an entry that was created when the proposal was submitted. -// https://github.com/decred/politeia/blob/master/politeiawww/api/www/v1/api.md#censorship-record -type CensorshipRecord struct { - TokenVal string `json:"token" storm:"unique"` - MerkleRoot string `json:"merkle"` - Signature string `json:"signature"` -} - -// AttachmentFile are files and documents submitted as proposal details. -// https://github.com/decred/politeia/blob/master/politeiawww/api/www/v1/api.md#file -type AttachmentFile struct { - Name string `json:"name"` - MimeType string `json:"mime"` - DigestKey string `json:"digest"` - Payload string `json:"payload"` -} - -// ProposalVotes defines the proposal status (Vote info for the public proposals). -// https://github.com/decred/politeia/blob/master/politeiawww/api/www/v1/api.md#proposal-vote-status -type ProposalVotes struct { - Token string `json:"token"` - VoteStatus VoteStatusType `json:"status"` - VoteResults []Results `json:"optionsresult"` - TotalVotes int64 `json:"totalvotes"` - Endheight string `json:"endheight"` - NumOfEligibleVotes int64 `json:"numofeligiblevotes"` - QuorumPercentage uint32 `json:"quorumpercentage"` - PassPercentage uint32 `json:"passpercentage"` -} - -// Votes defines a slice of VotesStatuses as returned by RouteAllVoteStatus. -type Votes struct { - Data []ProposalVotes `json:"votesstatus"` -} - -// Results defines the actual vote count info per the votes choices available. -type Results struct { - Option VoteOption `json:"option"` - VotesReceived int64 `json:"votesreceived"` -} - -// VoteOption defines the actual high level vote results for the specific agenda. -type VoteOption struct { - OptionID string `json:"id"` - Description string `json:"description"` - Bits int32 `json:"bits"` -} - -// ProposalStatusType defines the various proposal statuses available as referenced -// in https://github.com/decred/politeia/blob/master/politeiawww/api/www/v1/v1.go -type ProposalStatusType piapi.PropStatusT - -func (p ProposalStatusType) String() string { - return piapi.PropStatus[piapi.PropStatusT(p)] -} - -// VoteStatusType defines the various vote statuses available as referenced in -// https://github.com/decred/politeia/blob/master/politeiawww/api/www/v1/v1.go -type VoteStatusType piapi.PropVoteStatusT - -// ShorterDesc maps the short description to there respective vote status type. -var ShorterDesc = map[piapi.PropVoteStatusT]string{ - piapi.PropVoteStatusInvalid: "Invalid", - piapi.PropVoteStatusNotAuthorized: "Not Authorized", - piapi.PropVoteStatusAuthorized: "Authorized", - piapi.PropVoteStatusStarted: "Started", - piapi.PropVoteStatusFinished: "Finished", - piapi.PropVoteStatusDoesntExist: "Doesn't Exist", -} - -// ShortDesc returns the shorter vote status description. -func (s VoteStatusType) ShortDesc() string { - return ShorterDesc[piapi.PropVoteStatusT(s)] -} - -// LongDesc returns the long vote status description. -func (s VoteStatusType) LongDesc() string { - return piapi.PropVoteStatus[piapi.PropVoteStatusT(s)] -} - -// ProposalStateType defines the proposal state entry. -type ProposalStateType int8 - -const ( - // InvalidState defines the invalid state proposals. - InvalidState ProposalStateType = iota - - // UnvettedState defines the unvetted state proposals and includes proposals - // with a status of: - // * PropStatusNotReviewed - // * PropStatusUnreviewedChanges - // * PropStatusCensored - UnvettedState - - // VettedState defines the vetted state proposals and includes proposals - // with a status of: - // * PropStatusPublic - // * PropStatusAbandoned - VettedState - - // UnknownState indicates a proposal state that is unrecognized. - UnknownState + recordsv1 "github.com/decred/politeia/politeiawww/api/records/v1" + ticketvotev1 "github.com/decred/politeia/politeiawww/api/ticketvote/v1" ) -func (f ProposalStateType) String() string { - switch f { - case InvalidState: - return "invalid" - case UnvettedState: - return "unvetted" - case VettedState: - return "vetted" - default: - return "unknown" - } -} - -// ProposalStateFromStr converts the string into ProposalStateType value. -func ProposalStateFromStr(val string) ProposalStateType { - switch val { - case "invalid": - return InvalidState - case "unvetted": - return UnvettedState - case "vetted": - return VettedState - default: - return UnknownState - } -} - -// VotesStatuses returns the ShorterDesc map contents exclusive of Invalid and -// Doesn't exist statuses. -func VotesStatuses() map[VoteStatusType]string { - m := make(map[VoteStatusType]string) - for k, val := range ShorterDesc { - if k == piapi.PropVoteStatusInvalid || - k == piapi.PropVoteStatusDoesntExist { - continue - } - m[VoteStatusType(k)] = val - } - return m -} - -// IsEqual compares CensorshipRecord, Name, State, NumComments, StatusChangeMsg, -// Timestamp, CensoredDate, AbandonedDate, PublishedDate, Token, VoteStatus, -// TotalVotes and count of VoteResults between the two ProposalsInfo structs passed. -func (pi *ProposalInfo) IsEqual(b *ProposalInfo) bool { - if pi.CensorshipRecord != b.CensorshipRecord || pi.Name != b.Name || pi.State != b.State || - pi.NumComments != b.NumComments || pi.StatusChangeMsg != b.StatusChangeMsg || - pi.Status != b.Status || pi.Timestamp != b.Timestamp || pi.Token != b.Token || - pi.CensoredDate != b.CensoredDate || pi.AbandonedDate != b.AbandonedDate || +// ProposalRecord is the struct that holds all politeia data that dcrdata needs +// for each proposal. This is the object that is saved to stormdb. It uses data +// from three politeia API's: records, comments and ticketvote. +type ProposalRecord struct { + ID int `json:"id" storm:"id,increment"` + + // Record API data + State recordsv1.RecordStateT `json:"state"` + Status recordsv1.RecordStatusT `json:"status"` + Token string `json:"token"` + Version uint32 `json:"version"` + Timestamp uint64 `json:"timestamp" storm:"index"` + Username string `json:"username"` + + // Pi metadata + Name string `json:"name"` + + // User metadata + UserID string `json:"userid"` + + // Comments API data + CommentsCount int32 `json:"commentscount"` + + // Ticketvote API data + VoteStatus ticketvotev1.VoteStatusT `json:"votestatus"` + VoteResults []ticketvotev1.VoteResult `json:"voteresults"` + StatusChangeMsg string `json:"statuschangemsg"` + EligibleTickets uint32 `json:"eligibletickets"` + StartBlockHeight uint32 `json:"startblockheight"` + EndBlockHeight uint32 `json:"endblockheight"` + QuorumPercentage uint32 `json:"quorumpercentage"` + PassPercentage uint32 `json:"passpercentage"` + TotalVotes uint64 `json:"totalvotes"` + ChartData *ProposalChartData `json:"chartdata"` + + // Synced is used to indicate that this proposal is already fully + // synced with politeia server, and does not need to make any more + // http requests for this proposal + Synced bool `json:"synced"` + + // Timestamps + PublishedAt uint64 `json:"publishedat" storm:"index"` + CensoredAt uint64 `json:"censoredat"` + AbandonedAt uint64 `json:"abandonedat"` +} + +// ProposalChartData defines the data used to plot proposal ticket votes +// charts. +type ProposalChartData struct { + Yes []uint64 `json:"yes"` + No []uint64 `json:"no"` + Time []int64 `json:"time"` +} + +// IsEqual compares data between the two ProposalRecord structs passed. +func (pi *ProposalRecord) IsEqual(b ProposalRecord) bool { + if pi.Token != b.Token || pi.Name != b.Name || pi.State != b.State || + pi.Status != b.Status || pi.StatusChangeMsg != b.StatusChangeMsg || + pi.CommentsCount != b.CommentsCount || pi.Timestamp != b.Timestamp || pi.VoteStatus != b.VoteStatus || pi.TotalVotes != b.TotalVotes || - pi.PublishedDate != b.PublishedDate || len(pi.VoteResults) != len(b.VoteResults) { + pi.PublishedAt != b.PublishedAt || pi.CensoredAt != b.CensoredAt || + pi.AbandonedAt != b.AbandonedAt || pi.ChartData != b.ChartData { return false } return true @@ -219,57 +78,58 @@ func (pi *ProposalInfo) IsEqual(b *ProposalInfo) bool { // ProposalMetadata contains some status-dependent data representations for // display purposes. type ProposalMetadata struct { - // The start height of the vote. The end height is already part of the - // ProposalInfo struct. - StartHeight int64 - // Time until start for "Authorized" proposals, Time until done for "Started" - // proposals. - SecondsTil int64 - IsPassing bool - Approval float32 - Rejection float32 - Yes int64 - No int64 - VoteCount int64 - QuorumCount int64 - QuorumAchieved bool - PassPercent float32 -} - -// Metadata performs some common manipulations of the ProposalInfo data to -// prepare figures for display. Many of these manipulations require a tip height -// and a target block time for the network, so those must be provided as -// arguments. -func (pi *ProposalInfo) Metadata(tip, targetBlockTime int64) *ProposalMetadata { + // Time until start for "Authorized" proposals, Time until done for + // "Started" proposals. + SecondsTil int64 + IsPassing bool + Approval float32 + Rejection float32 + Yes int64 + No int64 + VoteCount int64 + QuorumCount int64 + QuorumAchieved bool + PassPercent float32 + VoteStatusDesc string + ProposalStateDesc string + ProposalStatusDesc string +} + +// Metadata performs some common manipulations of the ProposalRecord data to +// prepare figures for display. Many of these manipulations require a tip +// height and a target block time for the network, so those must be provided +// as arguments. +func (pi *ProposalRecord) Metadata(tip, targetBlockTime int64) *ProposalMetadata { meta := new(ProposalMetadata) - desc := pi.VoteStatus.ShortDesc() - switch desc { - case "Started", "Finished": - endHeight, _ := strconv.ParseInt(pi.ProposalVotes.Endheight, 10, 64) - meta.StartHeight = endHeight - windowSize + switch pi.VoteStatus { + case ticketvotev1.VoteStatusStarted, ticketvotev1.VoteStatusFinished, + ticketvotev1.VoteStatusApproved, ticketvotev1.VoteStatusRejected: for _, count := range pi.VoteResults { - switch count.Option.OptionID { + switch count.ID { case "yes": - meta.Yes = count.VotesReceived + meta.Yes = int64(count.Votes) case "no": - meta.No = count.VotesReceived + meta.No = int64(count.Votes) } } meta.VoteCount = meta.Yes + meta.No quorumPct := float32(pi.QuorumPercentage) / 100 - meta.QuorumCount = int64(quorumPct * float32(pi.NumOfEligibleVotes)) + meta.QuorumCount = int64(quorumPct * float32(pi.EligibleTickets)) meta.PassPercent = float32(pi.PassPercentage) / 100 - pctVoted := float32(meta.VoteCount) / float32(pi.NumOfEligibleVotes) + pctVoted := float32(meta.VoteCount) / float32(pi.EligibleTickets) meta.QuorumAchieved = pctVoted > quorumPct if meta.VoteCount > 0 { meta.Approval = float32(meta.Yes) / float32(meta.VoteCount) meta.Rejection = 1 - meta.Approval } meta.IsPassing = meta.Approval > meta.PassPercent - if desc == "Started" { - blocksLeft := endHeight - tip + if pi.VoteStatus == ticketvotev1.VoteStatusStarted { + blocksLeft := int64(pi.EndBlockHeight) - tip meta.SecondsTil = blocksLeft * targetBlockTime } } + meta.VoteStatusDesc = ticketvotev1.VoteStatuses[pi.VoteStatus] + meta.ProposalStateDesc = recordsv1.RecordStates[pi.State] + meta.ProposalStatusDesc = recordsv1.RecordStatuses[pi.Status] return meta } diff --git a/gov/politeia/util.go b/gov/politeia/util.go new file mode 100644 index 000000000..d6e891511 --- /dev/null +++ b/gov/politeia/util.go @@ -0,0 +1,118 @@ +package politeia + +import ( + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "io" + "strings" + + "github.com/decred/politeia/politeiad/plugins/usermd" + umplugin "github.com/decred/politeia/politeiad/plugins/usermd" + piv1 "github.com/decred/politeia/politeiawww/api/pi/v1" + recordsv1 "github.com/decred/politeia/politeiawww/api/records/v1" +) + +// userMetadataDecode returns the parsed data for the usermd plugin metadata +// stream. +func userMetadataDecode(ms []recordsv1.MetadataStream) (*usermd.UserMetadata, error) { + var userMD *usermd.UserMetadata + for _, m := range ms { + if m.PluginID != usermd.PluginID || + m.StreamID != usermd.StreamIDUserMetadata { + // This is not user metadata + continue + } + var um usermd.UserMetadata + err := json.Unmarshal([]byte(m.Payload), &um) + if err != nil { + return nil, err + } + userMD = &um + break + } + return userMD, nil +} + +// proposalMetadataDecode returns the parsed data for the pi plugin proposal +// metadata stream. +func proposalMetadataDecode(fs []recordsv1.File) (*piv1.ProposalMetadata, error) { + var pmp *piv1.ProposalMetadata + for _, f := range fs { + if f.Name != piv1.FileNameProposalMetadata { + continue + } + b, err := base64.StdEncoding.DecodeString(f.Payload) + if err != nil { + return nil, err + } + var pm piv1.ProposalMetadata + err = json.Unmarshal(b, &pm) + if err != nil { + return nil, err + } + pmp = &pm + break + } + if pmp == nil { + return nil, fmt.Errorf("proposal metadata not found") + } + return pmp, nil +} + +// statusChangeMetadataDecode returns the published, censored and abandoned +// dates from status change metadata streams. +func statusChangeMetadataDecode(md []recordsv1.MetadataStream) ([]uint64, string, error) { + var ( + statuses = make([]umplugin.StatusChangeMetadata, 0, 16) + ) + for _, v := range md { + if v.PluginID != umplugin.PluginID { + continue + } + + // Search for status change metadata + switch v.StreamID { + case umplugin.StreamIDStatusChanges: + d := json.NewDecoder(strings.NewReader(v.Payload)) + for { + var sc umplugin.StatusChangeMetadata + err := d.Decode(&sc) + if errors.Is(err, io.EOF) { + break + } else if err != nil { + return nil, "", err + } + statuses = append(statuses, sc) + } + } + } + + // Parse timestamps according to status + var ( + publishedAt, censoredAt, abandonedAt int64 + changeMsg string + changeMsgTimestamp int64 + ) + for _, v := range statuses { + if v.Timestamp > changeMsgTimestamp { + changeMsg = v.Reason + changeMsgTimestamp = v.Timestamp + } + switch recordsv1.RecordStatusT(v.Status) { + case recordsv1.RecordStatusPublic: + publishedAt = v.Timestamp + case recordsv1.RecordStatusCensored: + censoredAt = v.Timestamp + case recordsv1.RecordStatusArchived: + abandonedAt = v.Timestamp + } + } + + return []uint64{ + uint64(publishedAt), + uint64(censoredAt), + uint64(abandonedAt), + }, changeMsg, nil +} From 8dcbc6cbcafb8a16ccd39d31441003959ae1aacc Mon Sep 17 00:00:00 2001 From: Thiago Figueiredo Date: Wed, 28 Jul 2021 11:32:32 -0300 Subject: [PATCH 2/7] Address review comments & fix: properly paginate routes that need it --- cmd/dcrdata/explorer/explorerroutes.go | 1 + gov/go.mod | 2 +- gov/politeia/proposals.go | 344 ++++++++++++++++--------- gov/politeia/util.go | 82 ++++-- 4 files changed, 277 insertions(+), 152 deletions(-) diff --git a/cmd/dcrdata/explorer/explorerroutes.go b/cmd/dcrdata/explorer/explorerroutes.go index 0c10949da..2baa2c0eb 100644 --- a/cmd/dcrdata/explorer/explorerroutes.go +++ b/cmd/dcrdata/explorer/explorerroutes.go @@ -2403,6 +2403,7 @@ func (exp *explorerUI) ProposalsPage(w http.ResponseWriter, r *http.Request) { Limit: int64(rowsCount), VStatusFilter: int(filterBy), TotalCount: int64(count), + LastOffset: int64(lastOffset), PoliteiaURL: exp.politeiaURL, LastPropSync: exp.proposals.ProposalsLastSync(), TimePerBlock: int64(exp.ChainParams.TargetTimePerBlock.Seconds()), diff --git a/gov/go.mod b/gov/go.mod index 4a197c4a3..7270c738c 100644 --- a/gov/go.mod +++ b/gov/go.mod @@ -1,4 +1,4 @@ -module github.com/decred/dcrdata/gov/v4 +module github.com/decred/dcrdata/gov/v5 go 1.15 diff --git a/gov/politeia/proposals.go b/gov/politeia/proposals.go index 5d6ef6a75..2f258d76f 100644 --- a/gov/politeia/proposals.go +++ b/gov/politeia/proposals.go @@ -44,13 +44,16 @@ type ProposalsDB struct { APIPath string } +// NewProposalsDB opens an existing database or creates a new a storm DB +// instance with the provided path. It also sets up a new politeia http +// client and returns them on a proposals DB instance. func NewProposalsDB(politeiaURL, dbPath string) (*ProposalsDB, error) { // Validate arguments if politeiaURL == "" { - return nil, fmt.Errorf("missing Politeia URL") + return nil, errors.New("missing Politeia URL") } if dbPath == "" { - return nil, fmt.Errorf("missing db path") + return nil, errors.New("missing db path") } // Check path and open storm DB @@ -75,7 +78,7 @@ func NewProposalsDB(politeiaURL, dbPath string) (*ProposalsDB, error) { if err = db.Drop(&pitypes.ProposalRecord{}); err != nil { // If error due bucket not found was returned, ignore it. if !strings.Contains(err.Error(), "not found") { - return nil, fmt.Errorf("delete bucket struct failed: %v", err) + return nil, fmt.Errorf("delete bucket struct failed: %w", err) } } @@ -186,7 +189,7 @@ func (db *ProposalsDB) ProposalsAll(offset, rowsCount int, err = query.Skip(offset).Limit(rowsCount).Reverse().OrderBy("Timestamp"). Find(&proposals) if err != nil && !errors.Is(err, storm.ErrNotFound) { - log.Errorf("Failed to fetch data from Proposals DB: %v", err) + log.Errorf("Failed to fetch data from Proposals DB: %w", err) } return proposals, totalCount, nil @@ -203,113 +206,73 @@ func (db *ProposalsDB) ProposalByToken(token string) (*pitypes.ProposalRecord, e return db.proposal("Token", token) } -// fetchVettedTokens fetches all vetted tokens ordered by the timestamp of -// their last status change. -func (db *ProposalsDB) fetchVettedTokensInventory() ([]string, error) { - page := 0 - vettedTokens := []string{} - for { - inventoryReq := recordsv1.InventoryOrdered{ - State: recordsv1.RecordStateVetted, - Page: uint32(page + 1), - } - reply, err := db.client.RecordInventoryOrdered(inventoryReq) - if err != nil { - return nil, fmt.Errorf("Pi client RecordInventoryOrdered err: %v", - err) - } - - vettedTokens = append(vettedTokens, reply.Tokens...) - - // Break loop if we fetch last page - if len(reply.Tokens) < int(recordsv1.InventoryPageSize) { - break - } - } - return vettedTokens, nil -} - -// fetchRecordDetails fetches the record details of the given proposal tokens. -func (db *ProposalsDB) fetchRecordDetails(tokens []string) (map[string]recordsv1.Record, error) { - records := make(map[string]recordsv1.Record, len(tokens)) - for _, token := range tokens { - detailsReq := recordsv1.Details{ - Token: token, - } - dr, err := db.client.RecordDetails(detailsReq) - if err != nil { - return nil, fmt.Errorf("Pi client RecordDetails err: %v", err) - } - records[token] = *dr - } - - return records, nil -} - // fetchProposalsData returns the parsed vetted proposals from politeia // API's. It cooks up the data needed to save the proposals in stormdb. It // first fetches the proposal details, then comments and then vote summary. // This data is needed for the information provided in the dcrdata UI. The // data returned does not include ticket vote data. func (db *ProposalsDB) fetchProposalsData(tokens []string) ([]*pitypes.ProposalRecord, error) { - // Fetch record details for each token from the inventory + // Fetch record details for each token from the inventory. recordDetails, err := db.fetchRecordDetails(tokens) if err != nil { return nil, err } - // Fetch comments count for each token from the inventory - cr, err := db.client.CommentCount(commentsv1.Count{ - Tokens: tokens, - }) + // Fetch comments count for each token from the inventory. + commentsCounts, err := db.fetchCommentsCounts(tokens) if err != nil { - return nil, fmt.Errorf("Pi client CommentCount err: %v", err) + return nil, err } - commentsCounts := cr.Counts - // Fetch vote summary for each token from the inventory - sr, err := db.client.TicketVoteSummaries(ticketvotev1.Summaries{ - Tokens: tokens, - }) + // Fetch vote summary for each token from the inventory. + voteSummaries, err := db.fetchTicketVoteSummaries(tokens) if err != nil { - return nil, fmt.Errorf("Pi client TicketVoteSummaries err: %v", err) + return nil, err } - voteSummaries := sr.Summaries - - var proposals []*pitypes.ProposalRecord // Iterate through every record and feed data used by dcrdata + proposals := make([]*pitypes.ProposalRecord, 0, len(recordDetails)) for _, record := range recordDetails { - proposal := pitypes.ProposalRecord{} - // Record data - proposal.State = record.State - proposal.Status = record.Status - proposal.Version = record.Version - proposal.Timestamp = uint64(record.Timestamp) - proposal.Username = record.Username - proposal.Token = record.CensorshipRecord.Token + proposal := &pitypes.ProposalRecord{ + State: record.State, + Status: record.Status, + Version: record.Version, + Timestamp: uint64(record.Timestamp), + Username: record.Username, + Token: record.CensorshipRecord.Token, + } // Proposal metadata pm, err := proposalMetadataDecode(record.Files) if err != nil { - return nil, fmt.Errorf("proposalMetadataDecode err: %v", err) + return nil, fmt.Errorf("proposalMetadataDecode err: %w", err) } proposal.Name = pm.Name // User metadata um, err := userMetadataDecode(record.Metadata) if err != nil { - return nil, fmt.Errorf("userMetadataDecode err: %v", err) + return nil, fmt.Errorf("userMetadataDecode err: %w", err) } proposal.UserID = um.UserID // Comments count - proposal.CommentsCount = - int32(commentsCounts[record.CensorshipRecord.Token]) + commentsCount, ok := commentsCounts[proposal.Token] + if !ok { + log.Errorf("Comments count for proposal %v not returned by API", + proposal.Token) + continue + } + proposal.CommentsCount = int32(commentsCount) // Vote summary data - summary := voteSummaries[proposal.Token] + summary, ok := voteSummaries[proposal.Token] + if !ok { + log.Errorf("Vote summary for proposal %v not returned by API", + proposal.Token) + continue + } proposal.VoteStatus = summary.Status proposal.VoteResults = summary.Results proposal.EligibleTickets = summary.EligibleTickets @@ -325,29 +288,129 @@ func (db *ProposalsDB) fetchProposalsData(tokens []string) ([]*pitypes.ProposalR proposal.TotalVotes = totalVotes // Status change metadata - ts, changeMsg, err := statusChangeMetadataDecode(record.Metadata) + statusTimestamps, changeMsg, err := + statusChangeMetadataDecode(record.Metadata) if err != nil { - return nil, fmt.Errorf("statusChangeMetadataDecode err: %v", err) + return nil, fmt.Errorf("statusChangeMetadataDecode err: %w", err) } - proposal.PublishedAt = ts[0] - proposal.CensoredAt = ts[1] - proposal.AbandonedAt = ts[2] + proposal.PublishedAt = uint64(statusTimestamps.published) + proposal.CensoredAt = uint64(statusTimestamps.censored) + proposal.AbandonedAt = uint64(statusTimestamps.abandoned) proposal.StatusChangeMsg = changeMsg // Append proposal after inserting the relevant data - proposals = append(proposals, &proposal) + proposals = append(proposals, proposal) } return proposals, nil } +// fetchVettedTokens fetches all vetted tokens ordered by the timestamp of +// their last status change. +func (db *ProposalsDB) fetchVettedTokensInventory() ([]string, error) { + page := 1 + var vettedTokens []string + for { + inventoryReq := recordsv1.InventoryOrdered{ + State: recordsv1.RecordStateVetted, + Page: uint32(page), + } + reply, err := db.client.RecordInventoryOrdered(inventoryReq) + if err != nil { + return nil, fmt.Errorf("Pi client RecordInventoryOrdered err: %w", + err) + } + + vettedTokens = append(vettedTokens, reply.Tokens...) + + if len(reply.Tokens) < int(recordsv1.InventoryPageSize) { + // Break loop if we fetch last page. + break + } + + page++ + } + + return vettedTokens, nil +} + +// fetchRecordDetails fetches the record details of the given proposal tokens. +func (db *ProposalsDB) fetchRecordDetails(tokens []string) (map[string]*recordsv1.Record, error) { + records := make(map[string]*recordsv1.Record, len(tokens)) + for _, token := range tokens { + detailsReq := recordsv1.Details{ + Token: token, + } + dr, err := db.client.RecordDetails(detailsReq) + if err != nil { + return nil, fmt.Errorf("Pi client RecordDetails err: %w", err) + } + records[token] = dr + } + + return records, nil +} + +// fetchCommentsCounts fetches the comments counts for the given proposal tokens. +func (db *ProposalsDB) fetchCommentsCounts(tokens []string) (map[string]uint32, error) { + commentsCounts := make(map[string]uint32, len(tokens)) + paginatedTokens := paginateTokens(tokens, commentsv1.CountPageSize) + for i := 0; i < len(paginatedTokens); i++ { + cr, err := db.client.CommentCount(commentsv1.Count{ + Tokens: paginatedTokens[i], + }) + if err != nil { + return nil, fmt.Errorf("Pi client CommentCount err: %w", err) + } + for token, count := range cr.Counts { + commentsCounts[token] = count + } + } + return commentsCounts, nil +} + +// fetchTicketVoteSummaries fetches the vote summaries for the given proposal tokens. +func (db *ProposalsDB) fetchTicketVoteSummaries(tokens []string) (map[string]ticketvotev1.Summary, error) { + voteSummaries := make(map[string]ticketvotev1.Summary, len(tokens)) + paginatedTokens := paginateTokens(tokens, ticketvotev1.SummariesPageSize) + for i := 0; i < len(paginatedTokens); i++ { + sr, err := db.client.TicketVoteSummaries(ticketvotev1.Summaries{ + Tokens: paginatedTokens[i], + }) + if err != nil { + return nil, fmt.Errorf("Pi client TicketVoteSummaries err: %w", err) + } + for token := range sr.Summaries { + voteSummaries[token] = sr.Summaries[token] + } + } + return voteSummaries, nil +} + +// paginateTokens paginates tokens in a matrix according to the provided +// page size. +func paginateTokens(tokens []string, pageSize uint32) [][]string { + n := len(tokens)/int(pageSize) + 1 // number of pages needed + ts := make([][]string, n) + page := 0 + for i := 0; i < len(tokens); i++ { + if len(ts[page]) >= int(pageSize) { + page++ + } + ts[page] = append(ts[page], tokens[i]) + } + return ts +} + +// fetchTicketVoteResults fetches the vote data for the given proposal token, +// then builds and returns its parsed chart data. func (db *ProposalsDB) fetchTicketVoteResults(token string) (*pitypes.ProposalChartData, error) { // Fetch ticket votes details to acquire vote bits options info. details, err := db.client.TicketVoteDetails(ticketvotev1.Details{ Token: token, }) if err != nil { - return nil, fmt.Errorf("Pi client TicketVoteDetails err: %v", err) + return nil, fmt.Errorf("Pi client TicketVoteDetails err: %w", err) } // Maps the vote bits option to their respective string ID. @@ -360,55 +423,77 @@ func (db *ProposalsDB) fetchTicketVoteResults(token string) (*pitypes.ProposalCh Token: token, }) if err != nil { - return nil, fmt.Errorf("Pi client TicketVoteResults err: %v", err) + return nil, fmt.Errorf("Pi client TicketVoteResults err: %w", err) } - // Parse reply to proposal chart data - var chart pitypes.ProposalChartData - var timestamps []int64 - for _, v := range tvr.Votes { - bit, err := strconv.ParseUint(v.VoteBit, 16, 64) + // Parse proposal chart data from the ticket vote results reply and + // sort it afterwords. + type voteData struct { + yes, no uint64 + timestamp int64 + } + votes := make([]*voteData, 0, len(tvr.Votes)) + for iv := range tvr.Votes { + // Vote bit comes as a hexadecimal number in the format of a string. + // Convert it to uint64. + bit, err := strconv.ParseUint(tvr.Votes[iv].VoteBit, 16, 64) if err != nil { return nil, err } + + // Verify vote bit is valid. + err = voteBitVerify(details.Vote.Params.Options, + details.Vote.Params.Mask, bit) + if err != nil { + return nil, err + } + + // Parse relevant data. + var vd voteData switch voteOptsMap[bit] { case "yes": - chart.Yes = append(chart.Yes, 1) - chart.No = append(chart.No, 0) + vd.yes = 1 + vd.no = 0 case "no": - chart.No = append(chart.No, 1) - chart.Yes = append(chart.Yes, 0) + vd.no = 1 + vd.yes = 0 } - timestamps = append(timestamps, v.Timestamp) + vd.timestamp = tvr.Votes[iv].Timestamp + votes = append(votes, &vd) } - sort.Slice(timestamps, func(i, j int) bool { - return timestamps[i] < timestamps[j] + sort.Slice(votes, func(i, j int) bool { + return votes[i].timestamp < votes[j].timestamp }) - chart.Time = timestamps - return &chart, nil + // Build data for the returned proposal chart data object. + var ( + yes = make([]uint64, 0, len(votes)) + no = make([]uint64, 0, len(votes)) + times = make([]int64, 0, len(votes)) + ) + for _, vote := range votes { + yes = append(yes, vote.yes) + no = append(no, vote.no) + times = append(times, vote.timestamp) + } + + return &pitypes.ProposalChartData{ + Yes: yes, + No: no, + Time: times, + }, nil } -// proposalsSave saves the proposals data to the db. +// proposalsSave saves the batch proposals data to the db. This is ran when the +// proposals sync function finds new proposals that don't exist on our db yet. +// Before saving a proposal to the db, set the synced property to false to +// indicate that the proposal is not fully synced with politeia yet. func (db *ProposalsDB) proposalsSave(proposals []*pitypes.ProposalRecord) error { for _, proposal := range proposals { proposal.Synced = false err := db.dbP.Save(proposal) - if errors.Is(err, storm.ErrAlreadyExists) { - // Proposal exists, update instead of inserting new - data, err := db.ProposalByToken(proposal.Token) - if err != nil { - return fmt.Errorf("ProposalsDB ProposalByToken err: %v", err) - } - updateData := *proposal - updateData.ID = data.ID - err = db.dbP.Update(&updateData) - if err != nil { - return fmt.Errorf("stormdb update err: %v", err) - } - } if err != nil { - return fmt.Errorf("stormdb save err: %v", err) + return fmt.Errorf("stormdb save err: %w", err) } } @@ -421,7 +506,7 @@ func (db *ProposalsDB) proposal(searchBy, searchTerm string) (*pitypes.ProposalR var proposal pitypes.ProposalRecord err := db.dbP.Select(q.Eq(searchBy, searchTerm)).Limit(1).First(&proposal) if err != nil { - log.Errorf("Failed to fetch data from Proposals DB: %v", err) + log.Errorf("Failed to fetch data from Proposals DB: %w", err) return nil, err } @@ -434,48 +519,48 @@ func (db *ProposalsDB) proposalsNewUpdate() error { var proposals []*pitypes.ProposalRecord err := db.dbP.All(&proposals) if err != nil { - return fmt.Errorf("stormdb All err: %v", err) + return fmt.Errorf("stormdb All err: %w", err) } var tokens []string if len(proposals) == 0 { - // Empty db so first time fetching proposals, fetch all vetted tokens + // Empty db so first time fetching proposals, fetch all vetted tokens. vettedTokens, err := db.fetchVettedTokensInventory() if err != nil { return err } tokens = vettedTokens } else { - // Fetch inventory to search for new proposals + // Fetch inventory to search for new proposals. inventoryReq := recordsv1.InventoryOrdered{ State: recordsv1.RecordStateVetted, Page: 1, } reply, err := db.client.RecordInventoryOrdered(inventoryReq) if err != nil { - return fmt.Errorf("Pi client RecordInventoryOrdered err: %v", + return fmt.Errorf("Pi client RecordInventoryOrdered err: %w", err) } - // Create proposals map from local stormdb proposals + // Create proposals map from local stormdb proposals. proposalsMap := make(map[string]*pitypes.ProposalRecord, len(proposals)) for _, prop := range proposals { proposalsMap[prop.Token] = prop } - // Filter new proposals to be fetched + // Filter new proposals to be fetched. var tokensProposalsNew []string for _, token := range reply.Tokens { if _, ok := proposalsMap[token]; ok { continue } - // New proposal found + // New proposal found. tokensProposalsNew = append(tokensProposalsNew, token) } tokens = tokensProposalsNew } - // Fetch data for found tokens + // Fetch data for found tokens. var prs []*pitypes.ProposalRecord if len(tokens) > 0 { prs, err = db.fetchProposalsData(tokens) @@ -484,7 +569,7 @@ func (db *ProposalsDB) proposalsNewUpdate() error { } } - // Save proposals data on stormdb + // Save proposals data on the db. if len(prs) > 0 { err = db.proposalsSave(prs) if err != nil { @@ -512,9 +597,10 @@ func (db *ProposalsDB) proposalsInProgressUpdate() error { } for _, prop := range propsInProgress { + // Fetch fresh data for the proposal. proposals, err := db.fetchProposalsData([]string{prop.Token}) if err != nil { - return fmt.Errorf("fetchProposalsData failed with err: %s", err) + return fmt.Errorf("fetchProposalsData failed with err: %w", err) } proposal := proposals[0] @@ -527,7 +613,7 @@ func (db *ProposalsDB) proposalsInProgressUpdate() error { (prop.TotalVotes != proposal.TotalVotes || prop.ChartData == nil) { voteResults, err := db.fetchTicketVoteResults(prop.Token) if err != nil { - return fmt.Errorf("fetchTicketVoteResults failed with err: %s", err) + return fmt.Errorf("fetchTicketVoteResults failed with err: %w", err) } proposal.ChartData = voteResults } @@ -542,7 +628,7 @@ func (db *ProposalsDB) proposalsInProgressUpdate() error { err = db.dbP.Update(proposal) if err != nil { - return fmt.Errorf("storm db Update failed with err: %s", err) + return fmt.Errorf("storm db Update failed with err: %w", err) } } @@ -565,7 +651,8 @@ func (db *ProposalsDB) proposalsVoteResultsUpdate() error { q.And( q.Eq("VoteStatus", ticketvotev1.VoteStatusApproved), q.Eq("Synced", false), - ), q.And( + ), + q.And( q.Eq("VoteStatus", ticketvotev1.VoteStatusRejected), q.Eq("Synced", false), ), @@ -580,14 +667,15 @@ func (db *ProposalsDB) proposalsVoteResultsUpdate() error { for _, prop := range propsVotingComplete { voteResults, err := db.fetchTicketVoteResults(prop.Token) if err != nil { - return fmt.Errorf("fetchTicketVoteResults failed with err: %s", err) + return fmt.Errorf("fetchTicketVoteResults failed with err: %w", + err) } prop.ChartData = voteResults prop.Synced = true err = db.dbP.Update(prop) if err != nil { - return fmt.Errorf("storm db Update failed with err: %s", err) + return fmt.Errorf("storm db Update failed with err: %w", err) } } diff --git a/gov/politeia/util.go b/gov/politeia/util.go index d6e891511..863e1f4a4 100644 --- a/gov/politeia/util.go +++ b/gov/politeia/util.go @@ -9,9 +9,9 @@ import ( "strings" "github.com/decred/politeia/politeiad/plugins/usermd" - umplugin "github.com/decred/politeia/politeiad/plugins/usermd" piv1 "github.com/decred/politeia/politeiawww/api/pi/v1" recordsv1 "github.com/decred/politeia/politeiawww/api/records/v1" + ticketvotev1 "github.com/decred/politeia/politeiawww/api/ticketvote/v1" ) // userMetadataDecode returns the parsed data for the usermd plugin metadata @@ -61,23 +61,31 @@ func proposalMetadataDecode(fs []recordsv1.File) (*piv1.ProposalMetadata, error) return pmp, nil } +// statusTimestamps contains the published, censored and abandoned timestamps +// that are used on dcrdata's UI. +type statusTimestamps struct { + published int64 + censored int64 + abandoned int64 +} + // statusChangeMetadataDecode returns the published, censored and abandoned -// dates from status change metadata streams. -func statusChangeMetadataDecode(md []recordsv1.MetadataStream) ([]uint64, string, error) { - var ( - statuses = make([]umplugin.StatusChangeMetadata, 0, 16) - ) +// dates from status change metadata streams in the statusTimestamps struct. +// It also returns the status change message for the latest metadata stream. +func statusChangeMetadataDecode(md []recordsv1.MetadataStream) (*statusTimestamps, string, error) { + statuses := make([]usermd.StatusChangeMetadata, 0, 16) for _, v := range md { - if v.PluginID != umplugin.PluginID { + if v.PluginID != usermd.PluginID { continue } - // Search for status change metadata - switch v.StreamID { - case umplugin.StreamIDStatusChanges: + // Search for status change metadata. + if v.StreamID == usermd.StreamIDStatusChanges { + // The metadata payload is a stream of encoded json objects. + // Decode the payload accordingly. d := json.NewDecoder(strings.NewReader(v.Payload)) for { - var sc umplugin.StatusChangeMetadata + var sc usermd.StatusChangeMetadata err := d.Decode(&sc) if errors.Is(err, io.EOF) { break @@ -89,11 +97,16 @@ func statusChangeMetadataDecode(md []recordsv1.MetadataStream) ([]uint64, string } } - // Parse timestamps according to status + // Status change metadata represents the data associated with each + // status change a proposal undergoes. A proposal can only ever be + // on one status once. Therefore, walk the statuses metadatas and + // parse the data we need from the public, censored and abandoned + // status, as well as the status change message from the latest + // one. var ( - publishedAt, censoredAt, abandonedAt int64 - changeMsg string - changeMsgTimestamp int64 + timestamps statusTimestamps + changeMsg string + changeMsgTimestamp int64 ) for _, v := range statuses { if v.Timestamp > changeMsgTimestamp { @@ -102,17 +115,40 @@ func statusChangeMetadataDecode(md []recordsv1.MetadataStream) ([]uint64, string } switch recordsv1.RecordStatusT(v.Status) { case recordsv1.RecordStatusPublic: - publishedAt = v.Timestamp + timestamps.published = v.Timestamp case recordsv1.RecordStatusCensored: - censoredAt = v.Timestamp + timestamps.censored = v.Timestamp case recordsv1.RecordStatusArchived: - abandonedAt = v.Timestamp + timestamps.abandoned = v.Timestamp + } + } + + return ×tamps, changeMsg, nil +} + +// voteBitVerify verifies that the vote bit corresponds to a valid vote option. +// This verification matches the one used on politeia's code base to verify vote +// bits. +func voteBitVerify(options []ticketvotev1.VoteOption, mask, bit uint64) error { + if len(options) == 0 { + return fmt.Errorf("no vote options found") + } + if bit == 0 { + return fmt.Errorf("invalid bit 0x%x", bit) + } + + // Verify bit is included in mask + if mask&bit != bit { + return fmt.Errorf("invalid mask 0x%x bit 0x%x", mask, bit) + } + + // Verify bit is included in vote options + for _, v := range options { + if v.Bit == bit { + // Bit matches one of the options. We're done. + return nil } } - return []uint64{ - uint64(publishedAt), - uint64(censoredAt), - uint64(abandonedAt), - }, changeMsg, nil + return fmt.Errorf("bit 0x%x not found in vote options", bit) } From 3da51360bf268d42ecb460d8aae9f039651c6c12 Mon Sep 17 00:00:00 2001 From: Thiago Figueiredo Date: Wed, 28 Jul 2021 12:07:24 -0300 Subject: [PATCH 3/7] Remove axios from proposal_controller.js --- .../public/js/controllers/proposal_controller.js | 4 ++-- gov/politeia/proposals.go | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/cmd/dcrdata/public/js/controllers/proposal_controller.js b/cmd/dcrdata/public/js/controllers/proposal_controller.js index ab0ace3ba..3ccd71fe4 100644 --- a/cmd/dcrdata/public/js/controllers/proposal_controller.js +++ b/cmd/dcrdata/public/js/controllers/proposal_controller.js @@ -5,8 +5,8 @@ import globalEventBus from '../services/event_bus_service' import { getDefault } from '../helpers/module_helper' import { multiColumnBarPlotter, synchronize } from '../helpers/chart_helper' import dompurify from 'dompurify' -import axios from 'axios' import humanize from '../helpers/humanize_helper' +import { requestJSON } from '../helpers/http' const common = { labelsKMB: true, @@ -130,7 +130,7 @@ export default class extends Controller { this.approvalMeter = new MiniMeter(this.approvalMeterTarget, opts) } - const response = await axios.get('/api/proposal/' + this.tokenTarget.dataset.hash) + const response = await requestJSON('/api/proposal/' + this.tokenTarget.dataset.hash) chartData = response.data Dygraph = await getDefault( diff --git a/gov/politeia/proposals.go b/gov/politeia/proposals.go index 2f258d76f..283579bb8 100644 --- a/gov/politeia/proposals.go +++ b/gov/politeia/proposals.go @@ -492,6 +492,19 @@ func (db *ProposalsDB) proposalsSave(proposals []*pitypes.ProposalRecord) error for _, proposal := range proposals { proposal.Synced = false err := db.dbP.Save(proposal) + if errors.Is(err, storm.ErrAlreadyExists) { + // Proposal exists, update instead of inserting new. + data, err := db.ProposalByToken(proposal.Token) + if err != nil { + return fmt.Errorf("ProposalsDB ProposalByToken err: %v", err) + } + updateData := *proposal + updateData.ID = data.ID + err = db.dbP.Update(&updateData) + if err != nil { + return fmt.Errorf("stormdb update err: %v", err) + } + } if err != nil { return fmt.Errorf("stormdb save err: %w", err) } From b82c976b2f70be4fed266f24c5599004a168f12d Mon Sep 17 00:00:00 2001 From: Thiago Figueiredo Date: Wed, 28 Jul 2021 12:14:51 -0300 Subject: [PATCH 4/7] Use new gov/v5 --- cmd/dcrdata/api/apiroutes.go | 4 ++-- cmd/dcrdata/explorer/explorer.go | 4 ++-- cmd/dcrdata/explorer/explorerroutes.go | 4 ++-- cmd/dcrdata/go.mod | 4 ++-- cmd/dcrdata/log.go | 4 ++-- cmd/dcrdata/main.go | 4 ++-- gov/politeia/proposals.go | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/cmd/dcrdata/api/apiroutes.go b/cmd/dcrdata/api/apiroutes.go index 36f633c44..efc94a74b 100644 --- a/cmd/dcrdata/api/apiroutes.go +++ b/cmd/dcrdata/api/apiroutes.go @@ -32,8 +32,8 @@ import ( m "github.com/decred/dcrdata/cmd/dcrdata/middleware" "github.com/decred/dcrdata/exchanges/v3" - "github.com/decred/dcrdata/gov/v4/agendas" - "github.com/decred/dcrdata/gov/v4/politeia" + "github.com/decred/dcrdata/gov/v5/agendas" + "github.com/decred/dcrdata/gov/v5/politeia" apitypes "github.com/decred/dcrdata/v6/api/types" "github.com/decred/dcrdata/v6/db/cache" "github.com/decred/dcrdata/v6/db/dbtypes" diff --git a/cmd/dcrdata/explorer/explorer.go b/cmd/dcrdata/explorer/explorer.go index d02f486db..df85689bc 100644 --- a/cmd/dcrdata/explorer/explorer.go +++ b/cmd/dcrdata/explorer/explorer.go @@ -26,8 +26,8 @@ import ( "github.com/decred/dcrd/wire" "github.com/decred/dcrdata/exchanges/v3" - "github.com/decred/dcrdata/gov/v4/agendas" - pitypes "github.com/decred/dcrdata/gov/v4/politeia/types" + "github.com/decred/dcrdata/gov/v5/agendas" + pitypes "github.com/decred/dcrdata/gov/v5/politeia/types" "github.com/decred/dcrdata/v6/blockdata" "github.com/decred/dcrdata/v6/db/dbtypes" "github.com/decred/dcrdata/v6/explorer/types" diff --git a/cmd/dcrdata/explorer/explorerroutes.go b/cmd/dcrdata/explorer/explorerroutes.go index 2baa2c0eb..d86a08256 100644 --- a/cmd/dcrdata/explorer/explorerroutes.go +++ b/cmd/dcrdata/explorer/explorerroutes.go @@ -27,8 +27,8 @@ import ( "github.com/decred/dcrd/wire" "github.com/decred/dcrdata/exchanges/v3" - "github.com/decred/dcrdata/gov/v4/agendas" - pitypes "github.com/decred/dcrdata/gov/v4/politeia/types" + "github.com/decred/dcrdata/gov/v5/agendas" + pitypes "github.com/decred/dcrdata/gov/v5/politeia/types" "github.com/decred/dcrdata/v6/db/dbtypes" "github.com/decred/dcrdata/v6/explorer/types" "github.com/decred/dcrdata/v6/txhelpers" diff --git a/cmd/dcrdata/go.mod b/cmd/dcrdata/go.mod index 74e78edea..7c973ac3b 100644 --- a/cmd/dcrdata/go.mod +++ b/cmd/dcrdata/go.mod @@ -5,7 +5,7 @@ go 1.15 replace ( github.com/decred/dcrdata/db/dcrpg/v6 => ../../db/dcrpg/ github.com/decred/dcrdata/exchanges/v3 => ../../exchanges/ - github.com/decred/dcrdata/gov/v4 => ../../gov/ + github.com/decred/dcrdata/gov/v5 => ../../gov/ github.com/decred/dcrdata/v6 => ../../ ) @@ -23,7 +23,7 @@ require ( github.com/decred/dcrd/wire v1.4.0 github.com/decred/dcrdata/db/dcrpg/v6 v6.0.0 github.com/decred/dcrdata/exchanges/v3 v3.0.0 - github.com/decred/dcrdata/gov/v4 v4.0.0 + github.com/decred/dcrdata/gov/v5 v5.0.0 github.com/decred/dcrdata/v6 v6.0.0 github.com/decred/politeia v1.0.1 github.com/decred/slog v1.1.0 diff --git a/cmd/dcrdata/log.go b/cmd/dcrdata/log.go index a6bf2a23f..a8b1af9a9 100644 --- a/cmd/dcrdata/log.go +++ b/cmd/dcrdata/log.go @@ -21,8 +21,8 @@ import ( "github.com/decred/dcrdata/db/dcrpg/v6" "github.com/decred/dcrdata/exchanges/v3" - "github.com/decred/dcrdata/gov/v4/agendas" - "github.com/decred/dcrdata/gov/v4/politeia" + "github.com/decred/dcrdata/gov/v5/agendas" + "github.com/decred/dcrdata/gov/v5/politeia" "github.com/decred/dcrdata/v6/blockdata" "github.com/decred/dcrdata/v6/mempool" diff --git a/cmd/dcrdata/main.go b/cmd/dcrdata/main.go index c7403653f..bbb72166c 100644 --- a/cmd/dcrdata/main.go +++ b/cmd/dcrdata/main.go @@ -26,8 +26,8 @@ import ( "github.com/decred/dcrdata/db/dcrpg/v6" "github.com/decred/dcrdata/exchanges/v3" - "github.com/decred/dcrdata/gov/v4/agendas" - politeia "github.com/decred/dcrdata/gov/v4/politeia" + "github.com/decred/dcrdata/gov/v5/agendas" + politeia "github.com/decred/dcrdata/gov/v5/politeia" "github.com/decred/dcrdata/v6/blockdata" "github.com/decred/dcrdata/v6/db/cache" diff --git a/gov/politeia/proposals.go b/gov/politeia/proposals.go index 283579bb8..14bf0811d 100644 --- a/gov/politeia/proposals.go +++ b/gov/politeia/proposals.go @@ -15,7 +15,7 @@ import ( "github.com/asdine/storm/v3" "github.com/asdine/storm/v3/q" - pitypes "github.com/decred/dcrdata/gov/v4/politeia/types" + pitypes "github.com/decred/dcrdata/gov/v5/politeia/types" "github.com/decred/dcrdata/v6/semver" commentsv1 "github.com/decred/politeia/politeiawww/api/comments/v1" recordsv1 "github.com/decred/politeia/politeiawww/api/records/v1" From 4e976a282bd7f2527af5108d56577c91ce168ed9 Mon Sep 17 00:00:00 2001 From: Thiago Figueiredo Date: Wed, 28 Jul 2021 15:51:06 -0300 Subject: [PATCH 5/7] Rewind gov package to v4 --- cmd/dcrdata/api/apiroutes.go | 4 ++-- cmd/dcrdata/explorer/explorer.go | 4 ++-- cmd/dcrdata/explorer/explorerroutes.go | 4 ++-- cmd/dcrdata/go.mod | 4 ++-- cmd/dcrdata/log.go | 4 ++-- cmd/dcrdata/main.go | 4 ++-- gov/go.mod | 2 +- gov/politeia/proposals.go | 2 +- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cmd/dcrdata/api/apiroutes.go b/cmd/dcrdata/api/apiroutes.go index efc94a74b..36f633c44 100644 --- a/cmd/dcrdata/api/apiroutes.go +++ b/cmd/dcrdata/api/apiroutes.go @@ -32,8 +32,8 @@ import ( m "github.com/decred/dcrdata/cmd/dcrdata/middleware" "github.com/decred/dcrdata/exchanges/v3" - "github.com/decred/dcrdata/gov/v5/agendas" - "github.com/decred/dcrdata/gov/v5/politeia" + "github.com/decred/dcrdata/gov/v4/agendas" + "github.com/decred/dcrdata/gov/v4/politeia" apitypes "github.com/decred/dcrdata/v6/api/types" "github.com/decred/dcrdata/v6/db/cache" "github.com/decred/dcrdata/v6/db/dbtypes" diff --git a/cmd/dcrdata/explorer/explorer.go b/cmd/dcrdata/explorer/explorer.go index df85689bc..d02f486db 100644 --- a/cmd/dcrdata/explorer/explorer.go +++ b/cmd/dcrdata/explorer/explorer.go @@ -26,8 +26,8 @@ import ( "github.com/decred/dcrd/wire" "github.com/decred/dcrdata/exchanges/v3" - "github.com/decred/dcrdata/gov/v5/agendas" - pitypes "github.com/decred/dcrdata/gov/v5/politeia/types" + "github.com/decred/dcrdata/gov/v4/agendas" + pitypes "github.com/decred/dcrdata/gov/v4/politeia/types" "github.com/decred/dcrdata/v6/blockdata" "github.com/decred/dcrdata/v6/db/dbtypes" "github.com/decred/dcrdata/v6/explorer/types" diff --git a/cmd/dcrdata/explorer/explorerroutes.go b/cmd/dcrdata/explorer/explorerroutes.go index d86a08256..2baa2c0eb 100644 --- a/cmd/dcrdata/explorer/explorerroutes.go +++ b/cmd/dcrdata/explorer/explorerroutes.go @@ -27,8 +27,8 @@ import ( "github.com/decred/dcrd/wire" "github.com/decred/dcrdata/exchanges/v3" - "github.com/decred/dcrdata/gov/v5/agendas" - pitypes "github.com/decred/dcrdata/gov/v5/politeia/types" + "github.com/decred/dcrdata/gov/v4/agendas" + pitypes "github.com/decred/dcrdata/gov/v4/politeia/types" "github.com/decred/dcrdata/v6/db/dbtypes" "github.com/decred/dcrdata/v6/explorer/types" "github.com/decred/dcrdata/v6/txhelpers" diff --git a/cmd/dcrdata/go.mod b/cmd/dcrdata/go.mod index 7c973ac3b..74e78edea 100644 --- a/cmd/dcrdata/go.mod +++ b/cmd/dcrdata/go.mod @@ -5,7 +5,7 @@ go 1.15 replace ( github.com/decred/dcrdata/db/dcrpg/v6 => ../../db/dcrpg/ github.com/decred/dcrdata/exchanges/v3 => ../../exchanges/ - github.com/decred/dcrdata/gov/v5 => ../../gov/ + github.com/decred/dcrdata/gov/v4 => ../../gov/ github.com/decred/dcrdata/v6 => ../../ ) @@ -23,7 +23,7 @@ require ( github.com/decred/dcrd/wire v1.4.0 github.com/decred/dcrdata/db/dcrpg/v6 v6.0.0 github.com/decred/dcrdata/exchanges/v3 v3.0.0 - github.com/decred/dcrdata/gov/v5 v5.0.0 + github.com/decred/dcrdata/gov/v4 v4.0.0 github.com/decred/dcrdata/v6 v6.0.0 github.com/decred/politeia v1.0.1 github.com/decred/slog v1.1.0 diff --git a/cmd/dcrdata/log.go b/cmd/dcrdata/log.go index a8b1af9a9..a6bf2a23f 100644 --- a/cmd/dcrdata/log.go +++ b/cmd/dcrdata/log.go @@ -21,8 +21,8 @@ import ( "github.com/decred/dcrdata/db/dcrpg/v6" "github.com/decred/dcrdata/exchanges/v3" - "github.com/decred/dcrdata/gov/v5/agendas" - "github.com/decred/dcrdata/gov/v5/politeia" + "github.com/decred/dcrdata/gov/v4/agendas" + "github.com/decred/dcrdata/gov/v4/politeia" "github.com/decred/dcrdata/v6/blockdata" "github.com/decred/dcrdata/v6/mempool" diff --git a/cmd/dcrdata/main.go b/cmd/dcrdata/main.go index bbb72166c..c7403653f 100644 --- a/cmd/dcrdata/main.go +++ b/cmd/dcrdata/main.go @@ -26,8 +26,8 @@ import ( "github.com/decred/dcrdata/db/dcrpg/v6" "github.com/decred/dcrdata/exchanges/v3" - "github.com/decred/dcrdata/gov/v5/agendas" - politeia "github.com/decred/dcrdata/gov/v5/politeia" + "github.com/decred/dcrdata/gov/v4/agendas" + politeia "github.com/decred/dcrdata/gov/v4/politeia" "github.com/decred/dcrdata/v6/blockdata" "github.com/decred/dcrdata/v6/db/cache" diff --git a/gov/go.mod b/gov/go.mod index 7270c738c..4a197c4a3 100644 --- a/gov/go.mod +++ b/gov/go.mod @@ -1,4 +1,4 @@ -module github.com/decred/dcrdata/gov/v5 +module github.com/decred/dcrdata/gov/v4 go 1.15 diff --git a/gov/politeia/proposals.go b/gov/politeia/proposals.go index 14bf0811d..283579bb8 100644 --- a/gov/politeia/proposals.go +++ b/gov/politeia/proposals.go @@ -15,7 +15,7 @@ import ( "github.com/asdine/storm/v3" "github.com/asdine/storm/v3/q" - pitypes "github.com/decred/dcrdata/gov/v5/politeia/types" + pitypes "github.com/decred/dcrdata/gov/v4/politeia/types" "github.com/decred/dcrdata/v6/semver" commentsv1 "github.com/decred/politeia/politeiawww/api/comments/v1" recordsv1 "github.com/decred/politeia/politeiawww/api/records/v1" From c02a043dabad74f5e134307fafdf965c5d35939b Mon Sep 17 00:00:00 2001 From: Thiago Figueiredo Date: Thu, 29 Jul 2021 11:39:03 -0300 Subject: [PATCH 6/7] Review comments: cleanups/fixes & tests for paginateTokens --- gov/politeia/proposals.go | 57 +++++++------- gov/politeia/proposals_test.go | 136 +++++++++++++++++++++++++++++++++ gov/politeia/util.go | 71 ++++++++--------- 3 files changed, 197 insertions(+), 67 deletions(-) create mode 100644 gov/politeia/proposals_test.go diff --git a/gov/politeia/proposals.go b/gov/politeia/proposals.go index 283579bb8..bdb1b4d15 100644 --- a/gov/politeia/proposals.go +++ b/gov/politeia/proposals.go @@ -189,7 +189,7 @@ func (db *ProposalsDB) ProposalsAll(offset, rowsCount int, err = query.Skip(offset).Limit(rowsCount).Reverse().OrderBy("Timestamp"). Find(&proposals) if err != nil && !errors.Is(err, storm.ErrNotFound) { - log.Errorf("Failed to fetch data from Proposals DB: %w", err) + return nil, 0, err } return proposals, totalCount, nil @@ -260,8 +260,7 @@ func (db *ProposalsDB) fetchProposalsData(tokens []string) ([]*pitypes.ProposalR // Comments count commentsCount, ok := commentsCounts[proposal.Token] if !ok { - log.Errorf("Comments count for proposal %v not returned by API", - proposal.Token) + log.Errorf("Comments count for proposal %v not returned by API", proposal.Token) continue } proposal.CommentsCount = int32(commentsCount) @@ -269,8 +268,7 @@ func (db *ProposalsDB) fetchProposalsData(tokens []string) ([]*pitypes.ProposalR // Vote summary data summary, ok := voteSummaries[proposal.Token] if !ok { - log.Errorf("Vote summary for proposal %v not returned by API", - proposal.Token) + log.Errorf("Vote summary for proposal %v not returned by API", proposal.Token) continue } proposal.VoteStatus = summary.Status @@ -288,8 +286,7 @@ func (db *ProposalsDB) fetchProposalsData(tokens []string) ([]*pitypes.ProposalR proposal.TotalVotes = totalVotes // Status change metadata - statusTimestamps, changeMsg, err := - statusChangeMetadataDecode(record.Metadata) + statusTimestamps, changeMsg, err := statusChangeMetadataDecode(record.Metadata) if err != nil { return nil, fmt.Errorf("statusChangeMetadataDecode err: %w", err) } @@ -308,23 +305,26 @@ func (db *ProposalsDB) fetchProposalsData(tokens []string) ([]*pitypes.ProposalR // fetchVettedTokens fetches all vetted tokens ordered by the timestamp of // their last status change. func (db *ProposalsDB) fetchVettedTokensInventory() ([]string, error) { - page := 1 + page := uint32(1) var vettedTokens []string for { inventoryReq := recordsv1.InventoryOrdered{ State: recordsv1.RecordStateVetted, - Page: uint32(page), + Page: page, } reply, err := db.client.RecordInventoryOrdered(inventoryReq) if err != nil { - return nil, fmt.Errorf("Pi client RecordInventoryOrdered err: %w", - err) + return nil, fmt.Errorf("pi client RecordInventoryOrdered err: %w", err) } vettedTokens = append(vettedTokens, reply.Tokens...) if len(reply.Tokens) < int(recordsv1.InventoryPageSize) { - // Break loop if we fetch last page. + // Break loop if we fetch last page. An empty token slice is + // returned if we request an non-existent/empty page, so in the + // case of the last page size being equal to the limit page size, + // we'll fetch an empty page afterwords and know the last page was + // fetched. break } @@ -343,7 +343,7 @@ func (db *ProposalsDB) fetchRecordDetails(tokens []string) (map[string]*recordsv } dr, err := db.client.RecordDetails(detailsReq) if err != nil { - return nil, fmt.Errorf("Pi client RecordDetails err: %w", err) + return nil, fmt.Errorf("pi client RecordDetails err: %w", err) } records[token] = dr } @@ -355,12 +355,12 @@ func (db *ProposalsDB) fetchRecordDetails(tokens []string) (map[string]*recordsv func (db *ProposalsDB) fetchCommentsCounts(tokens []string) (map[string]uint32, error) { commentsCounts := make(map[string]uint32, len(tokens)) paginatedTokens := paginateTokens(tokens, commentsv1.CountPageSize) - for i := 0; i < len(paginatedTokens); i++ { + for i := range paginatedTokens { cr, err := db.client.CommentCount(commentsv1.Count{ Tokens: paginatedTokens[i], }) if err != nil { - return nil, fmt.Errorf("Pi client CommentCount err: %w", err) + return nil, fmt.Errorf("pi client CommentCount err: %w", err) } for token, count := range cr.Counts { commentsCounts[token] = count @@ -373,12 +373,12 @@ func (db *ProposalsDB) fetchCommentsCounts(tokens []string) (map[string]uint32, func (db *ProposalsDB) fetchTicketVoteSummaries(tokens []string) (map[string]ticketvotev1.Summary, error) { voteSummaries := make(map[string]ticketvotev1.Summary, len(tokens)) paginatedTokens := paginateTokens(tokens, ticketvotev1.SummariesPageSize) - for i := 0; i < len(paginatedTokens); i++ { + for i := range paginatedTokens { sr, err := db.client.TicketVoteSummaries(ticketvotev1.Summaries{ Tokens: paginatedTokens[i], }) if err != nil { - return nil, fmt.Errorf("Pi client TicketVoteSummaries err: %w", err) + return nil, fmt.Errorf("pi client TicketVoteSummaries err: %w", err) } for token := range sr.Summaries { voteSummaries[token] = sr.Summaries[token] @@ -390,7 +390,10 @@ func (db *ProposalsDB) fetchTicketVoteSummaries(tokens []string) (map[string]tic // paginateTokens paginates tokens in a matrix according to the provided // page size. func paginateTokens(tokens []string, pageSize uint32) [][]string { - n := len(tokens)/int(pageSize) + 1 // number of pages needed + n := len(tokens) / int(pageSize) // number of pages needed + if len(tokens)%int(pageSize) != 0 { + n++ + } ts := make([][]string, n) page := 0 for i := 0; i < len(tokens); i++ { @@ -410,7 +413,7 @@ func (db *ProposalsDB) fetchTicketVoteResults(token string) (*pitypes.ProposalCh Token: token, }) if err != nil { - return nil, fmt.Errorf("Pi client TicketVoteDetails err: %w", err) + return nil, fmt.Errorf("pi client TicketVoteDetails err: %w", err) } // Maps the vote bits option to their respective string ID. @@ -423,7 +426,7 @@ func (db *ProposalsDB) fetchTicketVoteResults(token string) (*pitypes.ProposalCh Token: token, }) if err != nil { - return nil, fmt.Errorf("Pi client TicketVoteResults err: %w", err) + return nil, fmt.Errorf("pi client TicketVoteResults err: %w", err) } // Parse proposal chart data from the ticket vote results reply and @@ -451,12 +454,15 @@ func (db *ProposalsDB) fetchTicketVoteResults(token string) (*pitypes.ProposalCh // Parse relevant data. var vd voteData switch voteOptsMap[bit] { - case "yes": + case ticketvotev1.VoteOptionIDApprove: vd.yes = 1 vd.no = 0 - case "no": + case ticketvotev1.VoteOptionIDReject: vd.no = 1 vd.yes = 0 + default: + log.Warnf("Unknown vote option ID %v", voteOptsMap[bit]) + continue } vd.timestamp = tvr.Votes[iv].Timestamp votes = append(votes, &vd) @@ -496,7 +502,7 @@ func (db *ProposalsDB) proposalsSave(proposals []*pitypes.ProposalRecord) error // Proposal exists, update instead of inserting new. data, err := db.ProposalByToken(proposal.Token) if err != nil { - return fmt.Errorf("ProposalsDB ProposalByToken err: %v", err) + return fmt.Errorf("ProposalsDB ProposalByToken err: %w", err) } updateData := *proposal updateData.ID = data.ID @@ -519,7 +525,7 @@ func (db *ProposalsDB) proposal(searchBy, searchTerm string) (*pitypes.ProposalR var proposal pitypes.ProposalRecord err := db.dbP.Select(q.Eq(searchBy, searchTerm)).Limit(1).First(&proposal) if err != nil { - log.Errorf("Failed to fetch data from Proposals DB: %w", err) + log.Errorf("Failed to fetch data from Proposals DB: %v", err) return nil, err } @@ -551,8 +557,7 @@ func (db *ProposalsDB) proposalsNewUpdate() error { } reply, err := db.client.RecordInventoryOrdered(inventoryReq) if err != nil { - return fmt.Errorf("Pi client RecordInventoryOrdered err: %w", - err) + return fmt.Errorf("pi client RecordInventoryOrdered err: %w", err) } // Create proposals map from local stormdb proposals. diff --git a/gov/politeia/proposals_test.go b/gov/politeia/proposals_test.go new file mode 100644 index 000000000..286f8c51c --- /dev/null +++ b/gov/politeia/proposals_test.go @@ -0,0 +1,136 @@ +package politeia + +import ( + "reflect" + "testing" +) + +func TestPaginateTokens(t *testing.T) { + tests := []struct { + name string + tokens []string + pageSize uint32 + want [][]string + }{ + { + name: "2 tokens / 5 page size", + tokens: []string{"x", "y"}, + pageSize: 5, + want: [][]string{ + {"x", "y"}, + }, + }, + { + name: "6 tokens / 5 page size", + tokens: []string{"x", "y", "z", "v", "q", "w"}, + pageSize: 5, + want: [][]string{ + {"x", "y", "z", "v", "q"}, + {"w"}, + }, + }, + { + name: "21 tokens / 5 page size", + tokens: []string{ + "x", "y", "z", "v", "q", "w", "x", "y", "z", "v", "q", "w", + "x", "y", "z", "v", "q", "w", "q", "w", "e", + }, + pageSize: 5, + want: [][]string{ + {"x", "y", "z", "v", "q"}, + {"w", "x", "y", "z", "v"}, + {"q", "w", "x", "y", "z"}, + {"v", "q", "w", "q", "w"}, + {"e"}, + }, + }, + { + name: "2 tokens / 4 page size", + tokens: []string{"x", "y"}, + pageSize: 4, + want: [][]string{ + {"x", "y"}, + }, + }, + { + name: "5 tokens / 4 page size", + tokens: []string{"x", "y", "z", "v", "q"}, + pageSize: 4, + want: [][]string{ + {"x", "y", "z", "v"}, + {"q"}, + }, + }, + { + name: "9 tokens / 4 page size", + tokens: []string{"x", "y", "z", "v", "q", "x", "y", "z", "v"}, + pageSize: 4, + want: [][]string{ + {"x", "y", "z", "v"}, + {"q", "x", "y", "z"}, + {"v"}, + }, + }, + { + name: "2 tokens / 3 page size", + tokens: []string{"x", "y"}, + pageSize: 3, + want: [][]string{ + {"x", "y"}, + }, + }, + { + name: "7 tokens / 3 page size", + tokens: []string{"x", "y", "z", "v", "q", "w", "e"}, + pageSize: 3, + want: [][]string{ + {"x", "y", "z"}, + {"v", "q", "w"}, + {"e"}, + }, + }, + { + name: "0 tokens / 2 page size", + tokens: []string{}, + pageSize: 2, + want: [][]string{}, + }, + { + name: "1 tokens / 2 page size", + tokens: []string{"x"}, + pageSize: 2, + want: [][]string{ + {"x"}, + }, + }, + { + name: "10 tokens / 2 page size", + tokens: []string{"x", "y", "z", "v", "q", "w", "x", "y", "z", "v"}, + pageSize: 2, + want: [][]string{ + {"x", "y"}, {"z", "v"}, {"q", "w"}, {"x", "y"}, {"z", "v"}, + }, + }, + { + name: "0 tokens / 1 page size", + tokens: []string{}, + pageSize: 1, + want: [][]string{}, + }, + { + name: "1 tokens / 1 page size", + tokens: []string{"x"}, + pageSize: 1, + want: [][]string{ + {"x"}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := paginateTokens(tt.tokens, tt.pageSize); !reflect.DeepEqual(got, tt.want) { + t.Errorf("paginateTokens() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/gov/politeia/util.go b/gov/politeia/util.go index 863e1f4a4..8829a882c 100644 --- a/gov/politeia/util.go +++ b/gov/politeia/util.go @@ -17,11 +17,9 @@ import ( // userMetadataDecode returns the parsed data for the usermd plugin metadata // stream. func userMetadataDecode(ms []recordsv1.MetadataStream) (*usermd.UserMetadata, error) { - var userMD *usermd.UserMetadata for _, m := range ms { - if m.PluginID != usermd.PluginID || - m.StreamID != usermd.StreamIDUserMetadata { - // This is not user metadata + if m.PluginID != usermd.PluginID || m.StreamID != usermd.StreamIDUserMetadata { + // This is not user metadata. continue } var um usermd.UserMetadata @@ -29,16 +27,14 @@ func userMetadataDecode(ms []recordsv1.MetadataStream) (*usermd.UserMetadata, er if err != nil { return nil, err } - userMD = &um - break + return &um, nil } - return userMD, nil + return nil, fmt.Errorf("user metadata not found") } // proposalMetadataDecode returns the parsed data for the pi plugin proposal // metadata stream. func proposalMetadataDecode(fs []recordsv1.File) (*piv1.ProposalMetadata, error) { - var pmp *piv1.ProposalMetadata for _, f := range fs { if f.Name != piv1.FileNameProposalMetadata { continue @@ -52,13 +48,9 @@ func proposalMetadataDecode(fs []recordsv1.File) (*piv1.ProposalMetadata, error) if err != nil { return nil, err } - pmp = &pm - break + return &pm, nil } - if pmp == nil { - return nil, fmt.Errorf("proposal metadata not found") - } - return pmp, nil + return nil, fmt.Errorf("proposal metadata not found") } // statusTimestamps contains the published, censored and abandoned timestamps @@ -73,36 +65,33 @@ type statusTimestamps struct { // dates from status change metadata streams in the statusTimestamps struct. // It also returns the status change message for the latest metadata stream. func statusChangeMetadataDecode(md []recordsv1.MetadataStream) (*statusTimestamps, string, error) { - statuses := make([]usermd.StatusChangeMetadata, 0, 16) + var statuses []usermd.StatusChangeMetadata for _, v := range md { - if v.PluginID != usermd.PluginID { + if v.PluginID != usermd.PluginID || v.StreamID != usermd.StreamIDStatusChanges { + // This is not status change metadata. continue } - // Search for status change metadata. - if v.StreamID == usermd.StreamIDStatusChanges { - // The metadata payload is a stream of encoded json objects. - // Decode the payload accordingly. - d := json.NewDecoder(strings.NewReader(v.Payload)) - for { - var sc usermd.StatusChangeMetadata - err := d.Decode(&sc) - if errors.Is(err, io.EOF) { - break - } else if err != nil { - return nil, "", err - } - statuses = append(statuses, sc) + // The metadata payload is a stream of encoded json objects. + // Decode the payload accordingly. + d := json.NewDecoder(strings.NewReader(v.Payload)) + for { + var sc usermd.StatusChangeMetadata + err := d.Decode(&sc) + if errors.Is(err, io.EOF) { + break + } else if err != nil { + return nil, "", err } + statuses = append(statuses, sc) } } - // Status change metadata represents the data associated with each - // status change a proposal undergoes. A proposal can only ever be - // on one status once. Therefore, walk the statuses metadatas and - // parse the data we need from the public, censored and abandoned - // status, as well as the status change message from the latest - // one. + // Status change metadata represents the data associated with each status + // change a proposal undergoes. A proposal can only ever be on one status + // once. Therefore, walk the statuses metadatas and parse the data we need + // from the public, censored and abandoned status, as well as the status + // change message from the latest one. var ( timestamps statusTimestamps changeMsg string @@ -127,19 +116,19 @@ func statusChangeMetadataDecode(md []recordsv1.MetadataStream) (*statusTimestamp } // voteBitVerify verifies that the vote bit corresponds to a valid vote option. -// This verification matches the one used on politeia's code base to verify vote -// bits. +// This verification matches the one used on politeia's code base to verify +// vote bits. func voteBitVerify(options []ticketvotev1.VoteOption, mask, bit uint64) error { if len(options) == 0 { return fmt.Errorf("no vote options found") } if bit == 0 { - return fmt.Errorf("invalid bit 0x%x", bit) + return fmt.Errorf("invalid bit %#x", bit) } // Verify bit is included in mask if mask&bit != bit { - return fmt.Errorf("invalid mask 0x%x bit 0x%x", mask, bit) + return fmt.Errorf("invalid mask 0x%x bit %#x", mask, bit) } // Verify bit is included in vote options @@ -150,5 +139,5 @@ func voteBitVerify(options []ticketvotev1.VoteOption, mask, bit uint64) error { } } - return fmt.Errorf("bit 0x%x not found in vote options", bit) + return fmt.Errorf("bit %#x not found in vote options", bit) } From b741fc247e6f6d39a9a8b67da2416fad08ccf6b9 Mon Sep 17 00:00:00 2001 From: Thiago Figueiredo Date: Fri, 6 Aug 2021 15:33:48 -0300 Subject: [PATCH 7/7] fix chartData response --- cmd/dcrdata/public/js/controllers/proposal_controller.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/dcrdata/public/js/controllers/proposal_controller.js b/cmd/dcrdata/public/js/controllers/proposal_controller.js index 3ccd71fe4..b27fb022f 100644 --- a/cmd/dcrdata/public/js/controllers/proposal_controller.js +++ b/cmd/dcrdata/public/js/controllers/proposal_controller.js @@ -130,8 +130,7 @@ export default class extends Controller { this.approvalMeter = new MiniMeter(this.approvalMeterTarget, opts) } - const response = await requestJSON('/api/proposal/' + this.tokenTarget.dataset.hash) - chartData = response.data + chartData = await requestJSON('/api/proposal/' + this.tokenTarget.dataset.hash) Dygraph = await getDefault( import(/* webpackChunkName: "dygraphs" */ '../vendor/dygraphs.min.js')