diff --git a/.drone-github.yml b/.drone-github.yml index d6b10f31924..991d07055a0 100644 --- a/.drone-github.yml +++ b/.drone-github.yml @@ -19,7 +19,7 @@ steps: # ====== Pipeline for pull requests ====== - name: build-PR - image: docker.pkg.github.com/vegaprotocol/devops-infra/cipipeline:1.11.13 + image: docker.pkg.github.com/vegaprotocol/devops-infra/cipipeline:1.14.4 pull: always volumes: - name: gocache @@ -43,7 +43,7 @@ steps: - ssh-keyscan github.com 1>~/.ssh/known_hosts 2>/dev/null ; chmod 0644 ~/.ssh/known_hosts - unset GITHUB_DEPLOY_SSH_PRIVATE_KEY # Build normal executable - - ./script/build.sh -t linux/amd64 + - ./script/build.sh -a build -t linux/amd64 # Build executable for sytstem-tests, with custom Governance parameters. 8760h is 24*365 hours. - env VEGA_GOVERNANCE_MIN_CLOSE=5s @@ -51,7 +51,7 @@ steps: VEGA_GOVERNANCE_MIN_ENACT=5s VEGA_GOVERNANCE_MAX_ENACT=8760h VEGA_GOVERNANCE_MIN_PARTICIPATION_STAKE=1 - ./script/build.sh -t linux/amd64 -s "-systemtests" + ./script/build.sh -a build -t linux/amd64 -s "-systemtests" depends_on: - fetch when: @@ -72,7 +72,7 @@ steps: - pull_request - name: test-PR - image: docker.pkg.github.com/vegaprotocol/devops-infra/cipipeline:1.11.13 + image: docker.pkg.github.com/vegaprotocol/devops-infra/cipipeline:1.14.4 volumes: - name: gocache path: /go/cache @@ -86,7 +86,7 @@ steps: from_secret: SLACK_HOOK_URL commands: - make retest - # More small checks. Run all, instead of exitng after first failure. + # More small checks. Run all, instead of exiting after first failure. - failed="" - for target in codeowners_check gqlgen_check print_check proto_check race vet ; do echo "$$COL_CYAN$$target$$COL_RESET" ; make "$$target" || failed="$$failed $$target" ; done @@ -159,7 +159,7 @@ steps: # ====== Pipeline for main branches (master, develop) and tags ====== - name: build-branch - image: docker.pkg.github.com/vegaprotocol/devops-infra/cipipeline:1.11.13 + image: docker.pkg.github.com/vegaprotocol/devops-infra/cipipeline:1.14.4 pull: always volumes: - name: gocache @@ -182,7 +182,7 @@ steps: - echo "$${GITHUB_DEPLOY_SSH_PRIVATE_KEY}" >~/.ssh/id_rsa ; chmod 0600 ~/.ssh/id_rsa - ssh-keyscan github.com 1>~/.ssh/known_hosts 2>/dev/null ; chmod 0644 ~/.ssh/known_hosts - unset GITHUB_DEPLOY_SSH_PRIVATE_KEY - - ./script/build.sh -t linux/amd64 + - ./script/build.sh -a build -t linux/amd64 depends_on: - fetch when: @@ -192,7 +192,7 @@ steps: - refs/tags/* - name: deploy_devnet - image: docker.pkg.github.com/vegaprotocol/devops-infra/cipipeline:1.11.13 + image: docker.pkg.github.com/vegaprotocol/devops-infra/cipipeline:1.14.4 volumes: - name: gopkg path: /go/pkg @@ -293,7 +293,7 @@ steps: - echo "$${GITHUB_DEPLOY_SSH_PRIVATE_KEY}" >~/.ssh/id_rsa ; chmod 0600 ~/.ssh/id_rsa - ssh-keyscan github.com 1>~/.ssh/known_hosts 2>/dev/null ; chmod 0644 ~/.ssh/known_hosts - unset GITHUB_DEPLOY_SSH_PRIVATE_KEY - - ./script/build.sh -T + - ./script/build.sh -a build -T depends_on: - build-branch when: @@ -317,7 +317,7 @@ steps: - build-multiarch - name: changelog_slack - image: docker.pkg.github.com/vegaprotocol/devops-infra/cipipeline:1.11.13 + image: docker.pkg.github.com/vegaprotocol/devops-infra/cipipeline:1.14.4 environment: SLACK_HOOK_URL: from_secret: SLACK_HOOK_URL diff --git a/.spelling b/.spelling index dfec8f5ed95..e363f23f73b 100644 --- a/.spelling +++ b/.spelling @@ -29,6 +29,7 @@ Suzdalnitski syslog tamlyn10 Tendermint +tendermint testnet tradable traderbot diff --git a/CHANGELOG.md b/CHANGELOG.md index 8793630f3eb..83a4a0917b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## 0.21.0 + +*2020-06-18* + +A follow-on from 0.20.1, this release includes a fix for the GraphQL API returning inconsistent values for the `side` field on orders, leading to Vega Console failing to submit orders. As a bonus there is another GraphQL improvement, and two fixes that return more correct values for filled network orders and expired orders. + +### Improvements + +- 💥 [#1820](https://github.com/vegaprotocol/vega/pull/1820) GraphQL: Non existent parties no longer return a GraphQL error +- 💥 [#1784](https://github.com/vegaprotocol/vega/pull/1784) GraphQL: Update schema and fix enum mappings from Proto +- 💥 [#1761](https://github.com/vegaprotocol/vega/pull/1761) Governance: Improve processing of Proposals +- [#1822](https://github.com/vegaprotocol/vega/pull/1822) Remove duplicate updates to `createdAt` +- [#1818](https://github.com/vegaprotocol/vega/pull/1818) Trades: Replace buffer with events +- [#1812](https://github.com/vegaprotocol/vega/pull/1812) Governance: Improve logging +- [#1810](https://github.com/vegaprotocol/vega/pull/1810) Execution: Set order status for fully filled network orders to be `FILLED` +- [#1803](https://github.com/vegaprotocol/vega/pull/1803) Matching: Set `updatedAt` when orders expire +- [#1780](https://github.com/vegaprotocol/vega/pull/1780) APIs: Reject `NETWORK` orders +- [#1792](https://github.com/vegaprotocol/vega/pull/1792) Update Golang to 1.14 and tendermint to 0.33.5 + ## 0.20.1 *2020-06-18* diff --git a/Dockerfile b/Dockerfile index 5d46530ef7f..896aa85aa92 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM docker.pkg.github.com/vegaprotocol/devops-infra/cipipeline:1.11.13 \ +FROM docker.pkg.github.com/vegaprotocol/devops-infra/cipipeline:1.14.4 \ AS builder RUN \ git config --global url."git@github.com:vegaprotocol".insteadOf "https://github.com/vegaprotocol" && \ @@ -19,10 +19,9 @@ RUN make install FROM scratch -ENTRYPOINT ["/vega"] -CMD ["node"] +ENTRYPOINT ["/vega-linux-amd64"] EXPOSE 3002/tcp 3003/tcp 3004/tcp 26658/tcp -COPY --from=builder /go/bin/dummyriskmodel / -COPY --from=builder /go/bin/vega / -COPY --from=builder /go/bin/vegaccount / -COPY --from=builder /go/bin/vegastream / +COPY --from=builder /go/bin/dummyriskmodel-linux-amd64 / +COPY --from=builder /go/bin/vega-linux-amd64 / +COPY --from=builder /go/bin/vegaccount-linux-amd64 / +COPY --from=builder /go/bin/vegastream-linux-amd64 / diff --git a/Makefile b/Makefile index 86436e92099..dbb807f9812 100644 --- a/Makefile +++ b/Makefile @@ -13,19 +13,19 @@ lint: ## Lint the files .PHONY: retest retest: ## Re-run all unit tests - @go test -count=1 ./... + @./script/build.sh -a retest .PHONY: test test: ## Run unit tests - @go test ./... + @./script/build.sh -a test .PHONY: integrationtest integrationtest: ## run integration tests, showing ledger movements and full scenario output - @go test -v ./integration/... -godog.format=pretty + @./script/build.sh -a integrationtest .PHONY: race race: ## Run data race detector - @env CGO_ENABLED=1 go test -race ./... + @./script/build.sh -a race .PHONY: mocks mocks: ## Make mocks @@ -38,57 +38,32 @@ msan: ## Run memory sanitizer .PHONY: vet vet: ## Run go vet - @go vet -all ./... - -.PHONY: vetshadow -vetshadow: # Run go vet with shadow detection - @go vet -shadow ./... 2>&1 | grep -vE '^(#|gateway/graphql/generated.go|proto/.*\.pb\.(gw\.)?go)' ; \ - code="$$?" ; test "$$code" -ne 0 - -.PHONY: .testCoverage.txt -.testCoverage.txt: - @go list ./... |grep -v '/gateway' | xargs go test -covermode=count -coverprofile="$@" - @go tool cover -func="$@" + @./script/build.sh -a vet .PHONY: coverage -coverage: .testCoverage.txt ## Generate global code coverage report - -.PHONY: .testCoverage.html -.testCoverage.html: .testCoverage.txt - @go tool cover -html="$^" -o "$@" - -.PHONY: coveragehtml -coveragehtml: .testCoverage.html ## Generate global code coverage report in HTML +coverage: ## Generate global code coverage report + @./script/build.sh -a coverage .PHONY: deps deps: ## Get the dependencies - @go mod download - @go mod vendor - @grep 'google/protobuf' go.mod | awk '{print "# " $$1 " " $$2 "\n"$$1"/src";}' >> vendor/modules.txt - @mkdir -p "$$GOPATH/pkg/mod/@indirect" - @modvendor -copy="**/*.proto" + @./script/build.sh -a deps .PHONY: build build: ## install the binaries in cmd/{progname}/ @d="" ; test -n "$$DEBUGVEGA" && d="-d" ; \ - ./script/build.sh $d -t linux/amd64 + ./script/build.sh $$d -a build -t default .PHONY: gofmtsimplify gofmtsimplify: @find . -path vendor -prune -o \( -name '*.go' -and -not -name '*_test.go' -and -not -name '*_mock.go' \) -print0 | xargs -0r gofmt -s -w .PHONY: install -install: SHELL:=/bin/bash install: ## install the binaries in GOPATH/bin - @source ./script/build.sh && set_version && set_ldflags && \ - echo "Version: $$version ($$version_hash)" && \ - for app in "$${apps[@]}" ; do \ - env CGO_ENABLED=1 go install -v -ldflags "$$ldflags" "./cmd/$$app" || exit 1 ; \ - done + @./script/build.sh -a install -t default .PHONY: gqlgen gqlgen: ## run gqlgen - @cd ./gateway/graphql/ && go run github.com/99designs/gqlgen --config gqlgen.yml + @./script/build.sh -a gqlgen .PHONY: gqlgen_check gqlgen_check: ## GraphQL: Check committed files match just-generated files @@ -107,7 +82,7 @@ ineffectassign: ## Check for ineffectual assignments if test "$$(echo -n "$$ia" | wc -l | awk '{print $$1}')" -gt 0 ; then echo "$$ia" ; exit 1 ; fi .PHONY: proto -proto: deps ## build proto definitions +proto: ## build proto definitions @./proto/generate.sh .PHONY: proto_check @@ -150,7 +125,7 @@ print_check: ## Check for fmt.Print functions in Go code if test "$$count" -gt 0 ; then exit 1 ; fi .PHONY: docker -docker: SHELL:=/bin/bash +docker: SHELL:=/usr/bin/env bash docker: ## Make docker container image from scratch @source ./script/build.sh && \ if ! test -f "$(HOME)/.ssh/id_rsa" ; then \ @@ -207,9 +182,7 @@ spellcheck: ## Run markdown spellcheck container # The integration directory is special, and contains a package called core_test. .PHONY: staticcheck staticcheck: ## Run statick analysis checks - @go list ./... | grep -v /integration | xargs staticcheck - @f="$$(mktemp)" && find integration -name '*.go' | xargs staticcheck | grep -v 'could not load export data' | tee "$$f" && \ - count="$$(wc -l <"$$f")" && rm -f "$$f" && if test "$$count" -gt 0 ; then exit 1 ; fi + @./script/build.sh -a staticcheck .PHONY: clean clean: SHELL:=/bin/bash diff --git a/README.md b/README.md index a01dca1d4b9..32546d647ed 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Vega -Version 0.20.1. +Version 0.21.0. A decentralised trading platform that allows pseudo-anonymous trading of derivatives on a blockchain. diff --git a/api/mocks/governance_data_service_mock.go b/api/mocks/governance_data_service_mock.go index 809d5062ed3..c6d817284bd 100644 --- a/api/mocks/governance_data_service_mock.go +++ b/api/mocks/governance_data_service_mock.go @@ -5,11 +5,10 @@ package mocks import ( - context "context" - reflect "reflect" - proto "code.vegaprotocol.io/vega/proto" + context "context" gomock "github.com/golang/mock/gomock" + reflect "reflect" ) // MockGovernanceDataService is a mock of GovernanceDataService interface diff --git a/api/trading_data.go b/api/trading_data.go index 75060aa4cec..4ccfb8d02bf 100644 --- a/api/trading_data.go +++ b/api/trading_data.go @@ -1151,7 +1151,7 @@ func (h *tradingDataService) Parties(ctx context.Context, req *empty.Empty) (*pr func (h *tradingDataService) PartyByID(ctx context.Context, req *protoapi.PartyByIDRequest) (*protoapi.PartyByIDResponse, error) { startTime := vegatime.Now() defer metrics.APIRequestAndTimeGRPC("PartyByID", startTime) - pty, err := validateParty(ctx, req.PartyID, h.PartyService) + pty, err := validateParty(ctx, h.log, req.PartyID, h.PartyService) if err != nil { return nil, err // validateParty already returns an API error, no need to additionally wrap } @@ -1252,7 +1252,7 @@ func validateMarket(ctx context.Context, marketID string, marketService MarketSe return mkt, nil } -func validateParty(ctx context.Context, partyID string, partyService PartyService) (*types.Party, error) { +func validateParty(ctx context.Context, log *logging.Logger, partyID string, partyService PartyService) (*types.Party, error) { var pty *types.Party var err error if len(partyID) == 0 { @@ -1260,7 +1260,13 @@ func validateParty(ctx context.Context, partyID string, partyService PartyServic } pty, err = partyService.GetByID(ctx, partyID) if err != nil { - return nil, apiError(codes.Internal, ErrPartyServiceGetByID, err) + // we just log the error here, then return an nil error. + // right now the only error possible is about not finding a party + // we just not an actual error + log.Debug("error getting party by ID", + logging.Error(err), + logging.String("party-id", partyID)) + err = nil } return pty, err } diff --git a/api/trading_test.go b/api/trading_test.go index b655a4f8764..d87dc403224 100644 --- a/api/trading_test.go +++ b/api/trading_test.go @@ -101,7 +101,7 @@ func getTestGRPCServer( blockchainClient := mocks.NewMockBlockchainClient(mockCtrl) blockchainClient.EXPECT().Health().AnyTimes().Return(&tmctypes.ResultHealth{}, nil) blockchainClient.EXPECT().GetStatus(gomock.Any()).AnyTimes().Return(&tmctypes.ResultStatus{ - NodeInfo: tmp2p.DefaultNodeInfo{Version: "0.32.9"}, + NodeInfo: tmp2p.DefaultNodeInfo{Version: "0.33.5"}, SyncInfo: tmctypes.SyncInfo{}, ValidatorInfo: tmctypes.ValidatorInfo{}, }, nil) diff --git a/blockchain/noop/noop.go b/blockchain/noop/noop.go index bb69c05112d..4bed2dd1786 100644 --- a/blockchain/noop/noop.go +++ b/blockchain/noop/noop.go @@ -132,7 +132,7 @@ func (n *NOOPChain) GetChainID(context.Context) (string, error) { func (n *NOOPChain) GetStatus(context.Context) (*tmctypes.ResultStatus, error) { return &tmctypes.ResultStatus{ NodeInfo: p2p.DefaultNodeInfo{ - Version: "0.32.9", + Version: "0.33.5", }, SyncInfo: tmctypes.SyncInfo{ CatchingUp: false, diff --git a/blockchain/tm/abci.go b/blockchain/tm/abci.go index 2887595410b..08c74b81e8d 100644 --- a/blockchain/tm/abci.go +++ b/blockchain/tm/abci.go @@ -117,7 +117,7 @@ func (a *AbciApplication) BeginBlock(beginBlock types.RequestBeginBlock) types.R if a.LogTimeDebug { a.log.Debug("Block time for height", logging.Int64("height", beginBlock.Header.Height), - logging.Int64("num-txs", beginBlock.Header.NumTxs), + // TODO: logging.Int64("num-txs", beginBlock.Header.NumTxs), logging.Int64("epoch-nano", beginBlock.Header.Time.UnixNano()), logging.String("time", beginBlock.Header.Time.String())) } diff --git a/blockchain/tm/client.go b/blockchain/tm/client.go index 78d66c8c479..e89b63856d8 100644 --- a/blockchain/tm/client.go +++ b/blockchain/tm/client.go @@ -7,7 +7,7 @@ import ( "code.vegaprotocol.io/vega/vegatime" - "github.com/tendermint/tendermint/rpc/client" + tmclihttp "github.com/tendermint/tendermint/rpc/client/http" tmctypes "github.com/tendermint/tendermint/rpc/core/types" tmtypes "github.com/tendermint/tendermint/types" ) @@ -18,7 +18,7 @@ var ( ) type Client struct { - tmclt *client.HTTP + tmclt *tmclihttp.HTTP } func NewClient(cfg Config) (*Client, error) { @@ -28,8 +28,12 @@ func NewClient(cfg Config) (*Client, error) { if len(cfg.ClientEndpoint) <= 0 { return nil, ErrEmptyClientEndpoint } + clt, err := tmclihttp.New(cfg.ClientAddr, cfg.ClientEndpoint) + if err != nil { + return nil, err + } return &Client{ - tmclt: client.NewHTTP(cfg.ClientAddr, cfg.ClientEndpoint), + tmclt: clt, }, nil } @@ -85,7 +89,7 @@ func (c *Client) Health() (*tmctypes.ResultHealth, error) { } func (c *Client) Validators() ([]*tmtypes.Validator, error) { - res, err := c.tmclt.Validators(nil) + res, err := c.tmclt.Validators(nil, 0, 100) if err != nil { return nil, err } diff --git a/blockchain/tm/server.go b/blockchain/tm/server.go index 55a391061a9..cc146d0061e 100644 --- a/blockchain/tm/server.go +++ b/blockchain/tm/server.go @@ -6,8 +6,8 @@ import ( "code.vegaprotocol.io/vega/logging" "github.com/tendermint/tendermint/abci/server" - cmn "github.com/tendermint/tendermint/libs/common" tmlog "github.com/tendermint/tendermint/libs/log" + "github.com/tendermint/tendermint/libs/service" ) // Server is an abstraction over the abci server @@ -15,7 +15,7 @@ type Server struct { Config log *logging.Logger abci *AbciApplication - srv cmn.Service + srv service.Service } // NewServer instantiate a new server diff --git a/broker/broker.go b/broker/broker.go index 8d70b693bb9..d22f4aa059c 100644 --- a/broker/broker.go +++ b/broker/broker.go @@ -16,6 +16,8 @@ type Subscriber interface { Closed() <-chan struct{} C() chan<- events.Event Types() []events.Type + SetID(id int) + ID() int } type subscription struct { @@ -103,6 +105,21 @@ func (b *Broker) getSubsByType(t events.Type) map[int]*subscription { // Subscribe registers a new subscriber, returning the key func (b *Broker) Subscribe(s Subscriber, req bool) int { b.mu.Lock() + k := b.sub(s, req) + b.mu.Unlock() + return k +} + +func (b *Broker) SubscribeBatch(req bool, subs ...Subscriber) { + b.mu.Lock() + for _, s := range subs { + k := b.sub(s, req) + s.SetID(k) + } + b.mu.Unlock() +} + +func (b *Broker) sub(s Subscriber, req bool) int { k := b.getKey() sub := subscription{ Subscriber: s, @@ -113,14 +130,12 @@ func (b *Broker) Subscribe(s Subscriber, req bool) int { if len(types) == 0 { types = []events.Type{events.All} } - // get subscribed types: for _, t := range types { if _, ok := b.tSubs[t]; !ok { b.tSubs[t] = map[int]*subscription{} } b.tSubs[t][k] = &sub } - b.mu.Unlock() return k } diff --git a/broker/mocks/subscriber_mock.go b/broker/mocks/subscriber_mock.go index 0f2db254e86..b8ad1afbb44 100644 --- a/broker/mocks/subscriber_mock.go +++ b/broker/mocks/subscriber_mock.go @@ -61,6 +61,20 @@ func (mr *MockSubscriberMockRecorder) Closed() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Closed", reflect.TypeOf((*MockSubscriber)(nil).Closed)) } +// ID mocks base method +func (m *MockSubscriber) ID() int { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ID") + ret0, _ := ret[0].(int) + return ret0 +} + +// ID indicates an expected call of ID +func (mr *MockSubscriberMockRecorder) ID() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ID", reflect.TypeOf((*MockSubscriber)(nil).ID)) +} + // Push mocks base method func (m *MockSubscriber) Push(arg0 events.Event) { m.ctrl.T.Helper() @@ -73,6 +87,18 @@ func (mr *MockSubscriberMockRecorder) Push(arg0 interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Push", reflect.TypeOf((*MockSubscriber)(nil).Push), arg0) } +// SetID mocks base method +func (m *MockSubscriber) SetID(arg0 int) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetID", arg0) +} + +// SetID indicates an expected call of SetID +func (mr *MockSubscriberMockRecorder) SetID(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetID", reflect.TypeOf((*MockSubscriber)(nil).SetID), arg0) +} + // Skip mocks base method func (m *MockSubscriber) Skip() <-chan struct{} { m.ctrl.T.Helper() diff --git a/cmd/vega/node.go b/cmd/vega/node.go index 65a93d4f0e5..6fac1b95c1d 100644 --- a/cmd/vega/node.go +++ b/cmd/vega/node.go @@ -93,6 +93,7 @@ type NodeCommand struct { orderSub *subscribers.OrderEvent accountSub *subscribers.AccountSub partySub *subscribers.PartySub + tradeSub *subscribers.TradeSub orderBuf *buffer.Order tradeBuf *buffer.Trade diff --git a/cmd/vega/node_pre.go b/cmd/vega/node_pre.go index c7b73abf9bb..5d2876ec000 100644 --- a/cmd/vega/node_pre.go +++ b/cmd/vega/node_pre.go @@ -251,6 +251,7 @@ func (l *NodeCommand) setupSubscibers() { l.orderSub = subscribers.NewOrderEvent(l.ctx, l.Log, l.orderStore) l.accountSub = subscribers.NewAccountSub(l.ctx, l.accounts) l.partySub = subscribers.NewPartySub(l.ctx, l.partyStore) + l.tradeSub = subscribers.NewTradeSub(l.ctx, l.tradeStore) } func (l *NodeCommand) setupBuffers() { @@ -336,18 +337,14 @@ func (l *NodeCommand) preRun(_ *cobra.Command, _ []string) (err error) { }() broker := broker.New(l.ctx) - _ = broker.Subscribe(l.transferSub, true) _ = broker.Subscribe(l.marketEventSub, false) // not required, use channel - _ = broker.Subscribe(l.orderSub, true) - _ = broker.Subscribe(l.accountSub, true) - _ = broker.Subscribe(l.partySub, true) + broker.SubscribeBatch(true, l.transferSub, l.orderSub, l.accountSub, l.partySub, l.tradeSub) // instantiate the execution engine l.executionEngine = execution.NewEngine( l.Log, l.conf.Execution, l.timeService, - l.tradeBuf, l.candleBuf, l.marketBuf, l.marketDataBuf, diff --git a/events/bus.go b/events/bus.go index fed44a5ecd1..599f3cc20d0 100644 --- a/events/bus.go +++ b/events/bus.go @@ -41,6 +41,7 @@ const ( OrderEvent AccountEvent PartyEvent + TradeEvent ) var ( @@ -57,6 +58,7 @@ var ( OrderEvent: "OrderEvent", AccountEvent: "AccountEvent", PartyEvent: "PartyEvent", + TradeEvent: "TradeEvent", } ) @@ -81,6 +83,9 @@ func New(ctx context.Context, v interface{}) (interface{}, error) { case types.Party: e := NewPartyEvent(ctx, tv) return e, nil + case types.Trade: + e := NewTradeEvent(ctx, tv) + return e, nil } return nil, ErrUnsuportedEvent } diff --git a/events/trade.go b/events/trade.go new file mode 100644 index 00000000000..d9eb861229c --- /dev/null +++ b/events/trade.go @@ -0,0 +1,23 @@ +package events + +import ( + "context" + + types "code.vegaprotocol.io/vega/proto" +) + +type Trade struct { + *Base + t types.Trade +} + +func NewTradeEvent(ctx context.Context, t types.Trade) *Trade { + return &Trade{ + Base: newBase(ctx, TradeEvent), + t: t, + } +} + +func (t *Trade) Trade() types.Trade { + return t.t +} diff --git a/execution/engine.go b/execution/engine.go index fe6624e8730..8d2455ccce8 100644 --- a/execution/engine.go +++ b/execution/engine.go @@ -45,13 +45,6 @@ type MarketBuf interface { Flush() error } -// TradeBuf ... -//go:generate go run github.com/golang/mock/mockgen -destination mocks/trade_buf_mock.go -package mocks code.vegaprotocol.io/vega/execution TradeBuf -type TradeBuf interface { - Add(types.Trade) - Flush() error -} - // SettlementBuf ... //go:generate go run github.com/golang/mock/mockgen -destination mocks/settlement_buf_mock.go -package mocks code.vegaprotocol.io/vega/execution SettlementBuf type SettlementBuf interface { @@ -122,7 +115,6 @@ type Engine struct { marketDataBuf MarketDataBuf marginLevelsBuf MarginLevelsBuf settleBuf SettlementBuf - tradeBuf TradeBuf lossSocBuf LossSocializationBuf proposalBuf ProposalBuf voteBuf VoteBuf @@ -137,7 +129,6 @@ func NewEngine( log *logging.Logger, executionConfig Config, time TimeService, - tradeBuf TradeBuf, candleBuf CandleBuf, marketBuf MarketBuf, marketDataBuf MarketDataBuf, @@ -165,7 +156,7 @@ func NewEngine( return nil } - networkParameters := governance.DefaultNetworkParameters() //TODO: store the parameters so proposals can update them + networkParameters := governance.DefaultNetworkParameters(log) //TODO: store the parameters so proposals can update them gengine := governance.NewEngine(log, executionConfig.Governance, networkParameters, cengine, proposalBuf, voteBuf, now) e := &Engine{ @@ -181,7 +172,6 @@ func NewEngine( marketDataBuf: marketDataBuf, marginLevelsBuf: marginLevelsBuf, settleBuf: settleBuf, - tradeBuf: tradeBuf, lossSocBuf: lossSocBuf, proposalBuf: proposalBuf, voteBuf: voteBuf, @@ -277,7 +267,6 @@ func (e *Engine) SubmitMarket(marketConfig *types.Market) error { e.party, marketConfig, e.candleBuf, - e.tradeBuf, e.marginLevelsBuf, e.settleBuf, now, @@ -321,10 +310,6 @@ func (e *Engine) SubmitOrder(ctx context.Context, order *types.Order) (*types.Or mkt, ok := e.markets[order.MarketID] if !ok { - t, err := e.time.GetTimeNow() - if err != nil { - order.CreatedAt = t.UnixNano() - } e.idgen.SetID(order) // adding rejected order to the buf @@ -535,10 +520,6 @@ func (e *Engine) Generate() error { // margins levels e.marginLevelsBuf.Flush() - // Trades - flush after orders so the traders reference an existing order - if err := e.tradeBuf.Flush(); err != nil { - return errors.Wrap(err, "failed to flush trades buffer") - } // Transfers // @TODO this event will be generated with a block context that has the trace ID // this will have the effect of flushing the transfer response buffer @@ -574,7 +555,7 @@ func (e *Engine) SubmitProposal(ctx context.Context, proposal *types.Proposal) e proposal.Timestamp = now.UnixNano() e.idgen.SetProposalID(proposal) - return e.governance.AddProposal(*proposal) + return e.governance.SubmitProposal(*proposal) } // VoteOnProposal sends proposal vote to governance engine diff --git a/execution/market.go b/execution/market.go index 2491d3e90d6..21bf112087c 100644 --- a/execution/market.go +++ b/execution/market.go @@ -47,6 +47,8 @@ var ( ErrInvalidAmendRemainQuantity = errors.New("incorrect remaining qty for a reduce by amend") // ErrEmptyMarketID is returned if processed market has an empty id ErrEmptyMarketID = errors.New("invalid market id (empty)") + // ErrInvalidOrderType is returned if processed order has an invalid order type + ErrInvalidOrderType = errors.New("invalid order type") networkPartyID = "network" ) @@ -78,7 +80,6 @@ type Market struct { partyEngine *Party // buffers - tradeBuf TradeBuf candleBuf CandleBuf marginLevelsBuf MarginLevelsBuf settleBuf SettlementBuf @@ -122,7 +123,6 @@ func NewMarket( partyEngine *Party, mkt *types.Market, candleBuf CandleBuf, - tradeBuf TradeBuf, marginLevelsBuf MarginLevelsBuf, settlementBuf SettlementBuf, now time.Time, @@ -185,7 +185,6 @@ func NewMarket( settlement: settleEngine, collateral: collateralEngine, partyEngine: partyEngine, - tradeBuf: tradeBuf, candleBuf: candleBuf, marginLevelsBuf: marginLevelsBuf, settleBuf: settlementBuf, @@ -351,7 +350,6 @@ func (m *Market) SubmitOrder(ctx context.Context, order *types.Order) (*types.Or // set those at the begining as even rejected order get through the buffers m.idgen.SetID(order) - order.CreatedAt = m.currentTime.UnixNano() order.Version = InitialOrderVersion if m.closed { @@ -362,6 +360,14 @@ func (m *Market) SubmitOrder(ctx context.Context, order *types.Order) (*types.Or return nil, ErrMarketClosed } + if order.Type == types.Order_TYPE_NETWORK { + // adding order to the buffer first + order.Status = types.Order_STATUS_REJECTED + order.Reason = types.OrderError_ORDER_ERROR_INVALID_TYPE + m.broker.Send(events.NewOrderEvent(ctx, order)) + return nil, ErrInvalidOrderType + } + // Validate market if order.MarketID != m.mkt.Id { // adding order to the buffer first @@ -511,7 +517,7 @@ func (m *Market) SubmitOrder(ctx context.Context, order *types.Order) (*types.Or trade.BuyOrder = confirmation.PassiveOrdersAffected[idx].Id } - m.tradeBuf.Add(*trade) + m.broker.Send(events.NewTradeEvent(ctx, *trade)) // Save to trade buffer for generating candles etc err := m.candleBuf.AddTrade(*trade) @@ -748,7 +754,7 @@ func (m *Market) resolveClosedOutTraders(ctx context.Context, distressedMarginEv // 0 out the BAD trader position trade.Type = types.Trade_TYPE_NETWORK_CLOSE_OUT_GOOD - m.tradeBuf.Add(*trade) + m.broker.Send(events.NewTradeEvent(ctx, *trade)) // Save to trade buffer for generating candles etc err = m.candleBuf.AddTrade(*trade) @@ -847,7 +853,7 @@ func (m *Market) zeroOutNetwork(ctx context.Context, traders []events.MarketPosi order.Size = tSize order.Remaining = 0 order.Side = nSide - order.Status = types.Order_STATUS_ACTIVE // ensure the status is always active + order.Status = types.Order_STATUS_FILLED // An order with no remaining must be filled m.idgen.SetID(&order) // this is the party order @@ -896,7 +902,7 @@ func (m *Market) zeroOutNetwork(ctx context.Context, traders []events.MarketPosi Timestamp: partyOrder.CreatedAt, Type: types.Trade_TYPE_NETWORK_CLOSE_OUT_BAD, } - m.tradeBuf.Add(trade) + m.broker.Send(events.NewTradeEvent(ctx, trade)) // 0 out margins levels for this trader marginLevels.PartyID = trader.Party() diff --git a/execution/market_test.go b/execution/market_test.go index 75e796bda9b..f4271b5b998 100644 --- a/execution/market_test.go +++ b/execution/market_test.go @@ -29,7 +29,6 @@ type testMarket struct { collateraEngine *collateral.Engine partyEngine *execution.Party candleStore *mocks.MockCandleBuf - tradeStore *mocks.MockTradeBuf settleBuf *mocks.MockSettlementBuf broker *mocks.MockBroker @@ -46,7 +45,6 @@ func getTestMarket(t *testing.T, now time.Time, closingAt time.Time) *testMarket matchingConfig := matching.NewDefaultConfig() candleStore := mocks.NewMockCandleBuf(ctrl) - tradeStore := mocks.NewMockTradeBuf(ctrl) settleBuf := mocks.NewMockSettlementBuf(ctrl) broker := mocks.NewMockBroker(ctrl) settleBuf.EXPECT().Add(gomock.Any()).AnyTimes() @@ -68,7 +66,7 @@ func getTestMarket(t *testing.T, now time.Time, closingAt time.Time) *testMarket mktEngine, err := execution.NewMarket( log, riskConfig, positionConfig, settlementConfig, matchingConfig, collateralEngine, partyEngine, &mkts[0], candleStore, - tradeStore, marginLevelsBuf, settleBuf, now, broker, execution.NewIDGen()) + marginLevelsBuf, settleBuf, now, broker, execution.NewIDGen()) assert.NoError(t, err) asset, err := mkts[0].GetAsset() @@ -84,7 +82,6 @@ func getTestMarket(t *testing.T, now time.Time, closingAt time.Time) *testMarket collateraEngine: collateralEngine, partyEngine: partyEngine, candleStore: candleStore, - tradeStore: tradeStore, settleBuf: settleBuf, broker: broker, now: now, @@ -222,7 +219,6 @@ func TestMarketWithTradeClosing(t *testing.T) { } // submit orders - tm.tradeStore.EXPECT().Add(gomock.Any()).AnyTimes() tm.broker.EXPECT().Send(gomock.Any()).AnyTimes() // tm.transferResponseStore.EXPECT().Add(gomock.Any()).AnyTimes() tm.candleStore.EXPECT().AddTrade(gomock.Any()).AnyTimes().Return(nil) @@ -280,7 +276,6 @@ func TestMarketGetMarginOnNewOrderEmptyBook(t *testing.T) { } // submit orders - tm.tradeStore.EXPECT().Add(gomock.Any()).AnyTimes() tm.broker.EXPECT().Send(gomock.Any()).AnyTimes() // tm.transferResponseStore.EXPECT().Add(gomock.Any()).AnyTimes() @@ -322,7 +317,6 @@ func TestMarketGetMarginOnFailNoFund(t *testing.T) { } // submit orders - tm.tradeStore.EXPECT().Add(gomock.Any()).AnyTimes() tm.broker.EXPECT().Send(gomock.Any()).AnyTimes() // tm.transferResponseStore.EXPECT().Add(gomock.Any()).AnyTimes() @@ -361,7 +355,6 @@ func TestMarketGetMarginOnAmendOrderCancelReplace(t *testing.T) { } // submit orders - tm.tradeStore.EXPECT().Add(gomock.Any()).AnyTimes() tm.broker.EXPECT().Send(gomock.Any()).AnyTimes() // tm.transferResponseStore.EXPECT().Add(gomock.Any()).AnyTimes() diff --git a/execution/mocks/trade_buf_mock.go b/execution/mocks/trade_buf_mock.go deleted file mode 100644 index cd2ee2354db..00000000000 --- a/execution/mocks/trade_buf_mock.go +++ /dev/null @@ -1,60 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: code.vegaprotocol.io/vega/execution (interfaces: TradeBuf) - -// Package mocks is a generated GoMock package. -package mocks - -import ( - proto "code.vegaprotocol.io/vega/proto" - gomock "github.com/golang/mock/gomock" - reflect "reflect" -) - -// MockTradeBuf is a mock of TradeBuf interface -type MockTradeBuf struct { - ctrl *gomock.Controller - recorder *MockTradeBufMockRecorder -} - -// MockTradeBufMockRecorder is the mock recorder for MockTradeBuf -type MockTradeBufMockRecorder struct { - mock *MockTradeBuf -} - -// NewMockTradeBuf creates a new mock instance -func NewMockTradeBuf(ctrl *gomock.Controller) *MockTradeBuf { - mock := &MockTradeBuf{ctrl: ctrl} - mock.recorder = &MockTradeBufMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockTradeBuf) EXPECT() *MockTradeBufMockRecorder { - return m.recorder -} - -// Add mocks base method -func (m *MockTradeBuf) Add(arg0 proto.Trade) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "Add", arg0) -} - -// Add indicates an expected call of Add -func (mr *MockTradeBufMockRecorder) Add(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Add", reflect.TypeOf((*MockTradeBuf)(nil).Add), arg0) -} - -// Flush mocks base method -func (m *MockTradeBuf) Flush() error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Flush") - ret0, _ := ret[0].(error) - return ret0 -} - -// Flush indicates an expected call of Flush -func (mr *MockTradeBufMockRecorder) Flush() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Flush", reflect.TypeOf((*MockTradeBuf)(nil).Flush)) -} diff --git a/execution/order_test.go b/execution/order_test.go index afffef9ed96..b9cf3ed015b 100644 --- a/execution/order_test.go +++ b/execution/order_test.go @@ -219,7 +219,6 @@ func TestMarkPriceUpdateAfterPartialFill(t *testing.T) { addAccount(tm, party1) addAccount(tm, party2) tm.broker.EXPECT().Send(gomock.Any()).AnyTimes() - tm.tradeStore.EXPECT().Add(gomock.Any()).AnyTimes() tm.candleStore.EXPECT().AddTrade(gomock.Any()).AnyTimes() orderBuy := &types.Order{ @@ -271,11 +270,11 @@ func TestExpireCancelGTCOrder(t *testing.T) { tm := getTestMarket(t, now, closingAt) addAccount(tm, party1) - tm.tradeStore.EXPECT().Add(gomock.Any()).AnyTimes() tm.candleStore.EXPECT().AddTrade(gomock.Any()).AnyTimes() tm.candleStore.EXPECT().Flush(gomock.Any(), gomock.Any()).AnyTimes() orderBuy := &types.Order{ + CreatedAt: 10000000000, Status: types.Order_STATUS_ACTIVE, TimeInForce: types.Order_TIF_GTC, Id: "someid", @@ -325,7 +324,6 @@ func TestAmendPartialFillCancelReplace(t *testing.T) { addAccount(tm, party1) addAccount(tm, party2) tm.broker.EXPECT().Send(gomock.Any()).AnyTimes() - tm.tradeStore.EXPECT().Add(gomock.Any()).AnyTimes() tm.candleStore.EXPECT().AddTrade(gomock.Any()).AnyTimes() tm.candleStore.EXPECT().Flush(gomock.Any(), gomock.Any()).AnyTimes() diff --git a/gateway/graphql/generated.go b/gateway/graphql/generated.go index 6232df9a302..3426f382ee7 100644 --- a/gateway/graphql/generated.go +++ b/gateway/graphql/generated.go @@ -262,10 +262,9 @@ type ComplexityRoot struct { } ProposalTerms struct { - Change func(childComplexity int) int - ClosingDatetime func(childComplexity int) int - EnactmentDatetime func(childComplexity int) int - MinParticipationStake func(childComplexity int) int + Change func(childComplexity int) int + ClosingDatetime func(childComplexity int) int + EnactmentDatetime func(childComplexity int) int } ProposalVote struct { @@ -366,6 +365,7 @@ type ComplexityRoot struct { SellOrder func(childComplexity int) int Seller func(childComplexity int) int Size func(childComplexity int) int + Type func(childComplexity int) int } TransactionSubmitted struct { @@ -381,7 +381,10 @@ type ComplexityRoot struct { MaxEnactInSeconds func(childComplexity int) int MinCloseInSeconds func(childComplexity int) int MinEnactInSeconds func(childComplexity int) int - MinParticipationStake func(childComplexity int) int + MinProposerBalance func(childComplexity int) int + MinVoterBalance func(childComplexity int) int + RequiredMajority func(childComplexity int) int + RequiredParticipation func(childComplexity int) int } Vote struct { @@ -560,6 +563,7 @@ type TradeResolver interface { Price(ctx context.Context, obj *proto.Trade) (string, error) Size(ctx context.Context, obj *proto.Trade) (string, error) CreatedAt(ctx context.Context, obj *proto.Trade) (string, error) + Type(ctx context.Context, obj *proto.Trade) (TradeType, error) } type executableSchema struct { @@ -1530,13 +1534,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.ProposalTerms.EnactmentDatetime(childComplexity), true - case "ProposalTerms.minParticipationStake": - if e.complexity.ProposalTerms.MinParticipationStake == nil { - break - } - - return e.complexity.ProposalTerms.MinParticipationStake(childComplexity), true - case "ProposalVote.proposalID": if e.complexity.ProposalVote.ProposalID == nil { break @@ -2163,6 +2160,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Trade.Size(childComplexity), true + case "Trade.type": + if e.complexity.Trade.Type == nil { + break + } + + return e.complexity.Trade.Type(childComplexity), true + case "TransactionSubmitted.success": if e.complexity.TransactionSubmitted.Success == nil { break @@ -2205,12 +2209,33 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.UpdateNetwork.MinEnactInSeconds(childComplexity), true - case "UpdateNetwork.minParticipationStake": - if e.complexity.UpdateNetwork.MinParticipationStake == nil { + case "UpdateNetwork.minProposerBalance": + if e.complexity.UpdateNetwork.MinProposerBalance == nil { + break + } + + return e.complexity.UpdateNetwork.MinProposerBalance(childComplexity), true + + case "UpdateNetwork.minVoterBalance": + if e.complexity.UpdateNetwork.MinVoterBalance == nil { + break + } + + return e.complexity.UpdateNetwork.MinVoterBalance(childComplexity), true + + case "UpdateNetwork.requiredMajority": + if e.complexity.UpdateNetwork.RequiredMajority == nil { + break + } + + return e.complexity.UpdateNetwork.RequiredMajority(childComplexity), true + + case "UpdateNetwork.requiredParticipation": + if e.complexity.UpdateNetwork.RequiredParticipation == nil { break } - return e.complexity.UpdateNetwork.MinParticipationStake(childComplexity), true + return e.complexity.UpdateNetwork.RequiredParticipation(childComplexity), true case "Vote.datetime": if e.complexity.Vote.Datetime == nil { @@ -3204,6 +3229,22 @@ type Trade { "RFC3339Nano for when the trade occurred" createdAt: String! + + "The type of trade" + type: TradeType! +} + +"Valid trade types" +enum TradeType { + + "Default trade type" + Default + + "Network close-out - good" + NetworkCloseOutGood + + "Network close-out - bad" + NetworkCloseOutBad } "An account record" @@ -3246,12 +3287,12 @@ enum OrderStatus { """ Active - "The order is cancelled, the order could be partially filled or unfilled before it was cancelled. It is not possible to cancel an order with 0 remaining." - Cancelled - "This order trades any amount and as much as possible and remains on the book until it either trades completely or expires." Expired + "The order is cancelled, the order could be partially filled or unfilled before it was cancelled. It is not possible to cancel an order with 0 remaining." + Cancelled + "This order was of type IOC or FOK and could not be processed by the matching engine due to lack of liquidity." Stopped @@ -3260,40 +3301,70 @@ enum OrderStatus { "This order was rejected while beeing processed in the core." Rejected + + "This order was partially filled." + PartiallyFilled } "Reason for the order beeing rejected by the core node" enum RejectionReason { + "Market id is invalid" InvalidMarketId + "Order id is invalid" InvalidOrderId + "Order is out of sequence" OrderOutOfSequence + "Remaining size in the order is invalid" InvalidRemainingSize + "Time has failed us" TimeFailure + "Unable to remove the order" OrderRemovalFailure + "Expiration time is invalid" InvalidExpirationTime + "Order reference is invalid" InvalidOrderReference + "Edit is not allowed" EditNotAllowed + "Order amend fail" OrderAmendFailure + "Order does not exist" OrderNotFound + "Party id is invalid" InvalidPartyId + "Market is closed" MarketClosed + "Margin check failed" MarginCheckFailed + + "Order missing general account" + MissingGeneralAccount + "An internal error happend" InternalError + + "Invalid size" + InvalidSize + + "Invalid persistence" + InvalidPersistence + + "Invalid type" + InvalidType } enum OrderType { @@ -3526,10 +3597,27 @@ type UpdateNetwork { maxEnactInSeconds: Int """ - Network parameter that restricts the minimum participation stake - required for a proposal to pass. + Network parameter that sets participation level required for any proposal to pass. + Value from 0 to 1. + """ + requiredParticipation: Float + """ + Network parameter that sets majority level required for any proposal to pass. + Value from 0.5 to 1. + """ + requiredMajority: Float + + """ + Network parameter that sets minimum balance required for a party + to be able to submit a new proposal. Value greater than 0 to 1. + """ + minProposerBalance: Float + + """ + Network parameter that sets minimum balance required for a party + to be able to cast a vote. Value greater than 0 to 1. """ - minParticipationStake: Int + minVoterBalance: Float } "Allows submitting a proposal for changing governance network parameters" @@ -3558,10 +3646,27 @@ input UpdateNetworkInput { maxEnactInSeconds: Int """ - Network parameter that restricts the minimum participation stake - required for a proposal to pass. + Network parameter that sets participation level required for any proposal to pass. + Value from 0 to 1. + """ + requiredParticipation: Float + """ + Network parameter that sets majority level required for any proposal to pass. + Value from 0.5 to 1. + """ + requiredMajority: Float + + """ + Network parameter that sets minimum balance required for a party + to be able to submit a new proposal. Value greater than 0 to 1. + """ + minProposerBalance: Float + + """ + Network parameter that sets minimum balance required for a party + to be able to cast a vote. Value greater than 0 to 1. """ - minParticipationStake: Int + minVoterBalance: Float } @@ -3569,31 +3674,54 @@ union ProposalChange = UpdateMarket | NewMarket | UpdateNetwork # there are no unions for input types as of today, see: https://github.com/graphql/graphql-spec/issues/488 type ProposalTerms { - "ISO-8601 time and date when voting closes for this proposal." + """ + ISO-8601 time and date when voting closes for this proposal. + Constrained by "minCloseInSeconds" and "maxCloseInSeconds" network parameters. + """ closingDatetime: String! - "ISO-8601 time and date when this proposal is executed (if passed). Note that it has to be after closing date time." + """ + ISO-8601 time and date when this proposal is executed (if passed). Note that it has to be after closing date time. + Constrained by "minEnactInSeconds" and "maxEnactInSeconds" network parameters. + """ enactmentDatetime: String! - "Minimum participation stake required for this proposal to pass" - minParticipationStake: Int! - "Actual change being introduced by the proposal" - change: ProposalChange + + "Actual change being introduced by the proposal - action the proposal triggers if passed and enacted." + change: ProposalChange! } # there are no unions for input types as of today, see: https://github.com/graphql/graphql-spec/issues/488 "Proposal terms input. Only one kind of change is expected. Proposals with no changes or more than one will not be accepted." input ProposalTermsInput { - "ISO-8601 time and date when voting closes for this proposal." + """ + ISO-8601 time and date when voting closes for this proposal. + Constrained by "minCloseInSeconds" and "maxCloseInSeconds" network parameters. + """ closingDatetime: String! - "ISO-8601 time and date when this proposal is executed (if passed). Note that it has to be after closing date time." + """ + ISO-8601 time and date when this proposal is executed (if passed). Note that it has to be after closing date time. + Constrained by "minEnactInSeconds" and "maxEnactInSeconds" network parameters. + """ enactmentDatetime: String! - "Minimum participation stake required for this proposal to pass" - minParticipationStake: Int! - - "Optional field to define update market change. If this is set along with another change, proposal will not be accepted." - updateMarket: UpdateMarketInput - "Optional field to define new market change. If this is set along with another change, proposal will not be accepted." + + + """ + Field defining new market change - the proposal will create new market if passed and enacted. + It can only be set if "updateMarket" and "updateNetwork" are not set (the proposal will be rejected otherwise). + One of "newMarket", "updateMarket", "updateNetwork" must be set (the proposal will be rejected otherwise). + """ newMarket: NewMarketInput - "Optional field to define an update of network parameters. If this is set along with another change, proposal will not be accepted." + """ + Field defining update market change - the proposal will update existing market if passed and enacted. + It can only be set if "newMarket" and "updateNetwork" are not set (the proposal will be rejected otherwise). + One of "newMarket", "updateMarket", "updateNetwork" must be set (the proposal will be rejected otherwise). + """ + updateMarket: UpdateMarketInput + + """ + Field defining update network change - the proposal will update Vega network parameters if passed and enacted. + It can only be set if "newMarket" and "updateMarket" are not set (the proposal will be rejected otherwise). + One of "newMarket", "updateMarket", "updateNetwork" must be set (the proposal will be rejected otherwise). + """ updateNetwork: UpdateNetworkInput } @@ -8922,7 +9050,7 @@ func (ec *executionContext) _ProposalTerms_enactmentDatetime(ctx context.Context return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _ProposalTerms_minParticipationStake(ctx context.Context, field graphql.CollectedField, obj *ProposalTerms) (ret graphql.Marshaler) { +func (ec *executionContext) _ProposalTerms_change(ctx context.Context, field graphql.CollectedField, obj *ProposalTerms) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -8939,7 +9067,7 @@ func (ec *executionContext) _ProposalTerms_minParticipationStake(ctx context.Con ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.MinParticipationStake, nil + return obj.Change, nil }) if err != nil { ec.Error(ctx, err) @@ -8951,40 +9079,9 @@ func (ec *executionContext) _ProposalTerms_minParticipationStake(ctx context.Con } return graphql.Null } - res := resTmp.(int) - fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) -} - -func (ec *executionContext) _ProposalTerms_change(ctx context.Context, field graphql.CollectedField, obj *ProposalTerms) (ret graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - fc := &graphql.FieldContext{ - Object: "ProposalTerms", - Field: field, - Args: nil, - IsMethod: false, - } - - ctx = graphql.WithFieldContext(ctx, fc) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.Change, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } res := resTmp.(ProposalChange) fc.Result = res - return ec.marshalOProposalChange2codeᚗvegaprotocolᚗioᚋvegaᚋgatewayᚋgraphqlᚐProposalChange(ctx, field.Selections, res) + return ec.marshalNProposalChange2codeᚗvegaprotocolᚗioᚋvegaᚋgatewayᚋgraphqlᚐProposalChange(ctx, field.Selections, res) } func (ec *executionContext) _ProposalVote_vote(ctx context.Context, field graphql.CollectedField, obj *ProposalVote) (ret graphql.Marshaler) { @@ -11760,6 +11857,40 @@ func (ec *executionContext) _Trade_createdAt(ctx context.Context, field graphql. return ec.marshalNString2string(ctx, field.Selections, res) } +func (ec *executionContext) _Trade_type(ctx context.Context, field graphql.CollectedField, obj *proto.Trade) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Trade", + Field: field, + Args: nil, + IsMethod: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Trade().Type(rctx, obj) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(TradeType) + fc.Result = res + return ec.marshalNTradeType2codeᚗvegaprotocolᚗioᚋvegaᚋgatewayᚋgraphqlᚐTradeType(ctx, field.Selections, res) +} + func (ec *executionContext) _TransactionSubmitted_success(ctx context.Context, field graphql.CollectedField, obj *TransactionSubmitted) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -11952,7 +12083,7 @@ func (ec *executionContext) _UpdateNetwork_maxEnactInSeconds(ctx context.Context return ec.marshalOInt2ᚖint(ctx, field.Selections, res) } -func (ec *executionContext) _UpdateNetwork_minParticipationStake(ctx context.Context, field graphql.CollectedField, obj *UpdateNetwork) (ret graphql.Marshaler) { +func (ec *executionContext) _UpdateNetwork_requiredParticipation(ctx context.Context, field graphql.CollectedField, obj *UpdateNetwork) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -11969,7 +12100,7 @@ func (ec *executionContext) _UpdateNetwork_minParticipationStake(ctx context.Con ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.MinParticipationStake, nil + return obj.RequiredParticipation, nil }) if err != nil { ec.Error(ctx, err) @@ -11978,9 +12109,102 @@ func (ec *executionContext) _UpdateNetwork_minParticipationStake(ctx context.Con if resTmp == nil { return graphql.Null } - res := resTmp.(*int) + res := resTmp.(*float64) fc.Result = res - return ec.marshalOInt2ᚖint(ctx, field.Selections, res) + return ec.marshalOFloat2ᚖfloat64(ctx, field.Selections, res) +} + +func (ec *executionContext) _UpdateNetwork_requiredMajority(ctx context.Context, field graphql.CollectedField, obj *UpdateNetwork) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "UpdateNetwork", + Field: field, + Args: nil, + IsMethod: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.RequiredMajority, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*float64) + fc.Result = res + return ec.marshalOFloat2ᚖfloat64(ctx, field.Selections, res) +} + +func (ec *executionContext) _UpdateNetwork_minProposerBalance(ctx context.Context, field graphql.CollectedField, obj *UpdateNetwork) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "UpdateNetwork", + Field: field, + Args: nil, + IsMethod: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.MinProposerBalance, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*float64) + fc.Result = res + return ec.marshalOFloat2ᚖfloat64(ctx, field.Selections, res) +} + +func (ec *executionContext) _UpdateNetwork_minVoterBalance(ctx context.Context, field graphql.CollectedField, obj *UpdateNetwork) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "UpdateNetwork", + Field: field, + Args: nil, + IsMethod: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.MinVoterBalance, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*float64) + fc.Result = res + return ec.marshalOFloat2ᚖfloat64(ctx, field.Selections, res) } func (ec *executionContext) _Vote_value(ctx context.Context, field graphql.CollectedField, obj *Vote) (ret graphql.Marshaler) { @@ -13464,9 +13688,9 @@ func (ec *executionContext) unmarshalInputProposalTermsInput(ctx context.Context if err != nil { return it, err } - case "minParticipationStake": + case "newMarket": var err error - it.MinParticipationStake, err = ec.unmarshalNInt2int(ctx, v) + it.NewMarket, err = ec.unmarshalONewMarketInput2ᚖcodeᚗvegaprotocolᚗioᚋvegaᚋgatewayᚋgraphqlᚐNewMarketInput(ctx, v) if err != nil { return it, err } @@ -13476,12 +13700,6 @@ func (ec *executionContext) unmarshalInputProposalTermsInput(ctx context.Context if err != nil { return it, err } - case "newMarket": - var err error - it.NewMarket, err = ec.unmarshalONewMarketInput2ᚖcodeᚗvegaprotocolᚗioᚋvegaᚋgatewayᚋgraphqlᚐNewMarketInput(ctx, v) - if err != nil { - return it, err - } case "updateNetwork": var err error it.UpdateNetwork, err = ec.unmarshalOUpdateNetworkInput2ᚖcodeᚗvegaprotocolᚗioᚋvegaᚋgatewayᚋgraphqlᚐUpdateNetworkInput(ctx, v) @@ -13650,9 +13868,27 @@ func (ec *executionContext) unmarshalInputUpdateNetworkInput(ctx context.Context if err != nil { return it, err } - case "minParticipationStake": + case "requiredParticipation": + var err error + it.RequiredParticipation, err = ec.unmarshalOFloat2ᚖfloat64(ctx, v) + if err != nil { + return it, err + } + case "requiredMajority": var err error - it.MinParticipationStake, err = ec.unmarshalOInt2ᚖint(ctx, v) + it.RequiredMajority, err = ec.unmarshalOFloat2ᚖfloat64(ctx, v) + if err != nil { + return it, err + } + case "minProposerBalance": + var err error + it.MinProposerBalance, err = ec.unmarshalOFloat2ᚖfloat64(ctx, v) + if err != nil { + return it, err + } + case "minVoterBalance": + var err error + it.MinVoterBalance, err = ec.unmarshalOFloat2ᚖfloat64(ctx, v) if err != nil { return it, err } @@ -15575,13 +15811,11 @@ func (ec *executionContext) _ProposalTerms(ctx context.Context, sel ast.Selectio if out.Values[i] == graphql.Null { invalids++ } - case "minParticipationStake": - out.Values[i] = ec._ProposalTerms_minParticipationStake(ctx, field, obj) + case "change": + out.Values[i] = ec._ProposalTerms_change(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } - case "change": - out.Values[i] = ec._ProposalTerms_change(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -16464,6 +16698,20 @@ func (ec *executionContext) _Trade(ctx context.Context, sel ast.SelectionSet, ob } return res }) + case "type": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Trade_type(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -16548,8 +16796,14 @@ func (ec *executionContext) _UpdateNetwork(ctx context.Context, sel ast.Selectio out.Values[i] = ec._UpdateNetwork_minEnactInSeconds(ctx, field, obj) case "maxEnactInSeconds": out.Values[i] = ec._UpdateNetwork_maxEnactInSeconds(ctx, field, obj) - case "minParticipationStake": - out.Values[i] = ec._UpdateNetwork_minParticipationStake(ctx, field, obj) + case "requiredParticipation": + out.Values[i] = ec._UpdateNetwork_requiredParticipation(ctx, field, obj) + case "requiredMajority": + out.Values[i] = ec._UpdateNetwork_requiredMajority(ctx, field, obj) + case "minProposerBalance": + out.Values[i] = ec._UpdateNetwork_minProposerBalance(ctx, field, obj) + case "minVoterBalance": + out.Values[i] = ec._UpdateNetwork_minVoterBalance(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -17302,6 +17556,16 @@ func (ec *executionContext) marshalNProposal2ᚖcodeᚗvegaprotocolᚗioᚋvega return ec._Proposal(ctx, sel, v) } +func (ec *executionContext) marshalNProposalChange2codeᚗvegaprotocolᚗioᚋvegaᚋgatewayᚋgraphqlᚐProposalChange(ctx context.Context, sel ast.SelectionSet, v ProposalChange) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._ProposalChange(ctx, sel, v) +} + func (ec *executionContext) unmarshalNProposalState2codeᚗvegaprotocolᚗioᚋvegaᚋgatewayᚋgraphqlᚐProposalState(ctx context.Context, v interface{}) (ProposalState, error) { var res ProposalState return res, res.UnmarshalGQL(v) @@ -17511,6 +17775,15 @@ func (ec *executionContext) marshalNTrade2ᚖcodeᚗvegaprotocolᚗioᚋvegaᚋp return ec._Trade(ctx, sel, v) } +func (ec *executionContext) unmarshalNTradeType2codeᚗvegaprotocolᚗioᚋvegaᚋgatewayᚋgraphqlᚐTradeType(ctx context.Context, v interface{}) (TradeType, error) { + var res TradeType + return res, res.UnmarshalGQL(v) +} + +func (ec *executionContext) marshalNTradeType2codeᚗvegaprotocolᚗioᚋvegaᚋgatewayᚋgraphqlᚐTradeType(ctx context.Context, sel ast.SelectionSet, v TradeType) graphql.Marshaler { + return v +} + func (ec *executionContext) marshalNTradingMode2codeᚗvegaprotocolᚗioᚋvegaᚋgatewayᚋgraphqlᚐTradingMode(ctx context.Context, sel ast.SelectionSet, v TradingMode) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { @@ -17946,6 +18219,29 @@ func (ec *executionContext) unmarshalODiscreteTradingInput2ᚖcodeᚗvegaprotoco return &res, err } +func (ec *executionContext) unmarshalOFloat2float64(ctx context.Context, v interface{}) (float64, error) { + return graphql.UnmarshalFloat(v) +} + +func (ec *executionContext) marshalOFloat2float64(ctx context.Context, sel ast.SelectionSet, v float64) graphql.Marshaler { + return graphql.MarshalFloat(v) +} + +func (ec *executionContext) unmarshalOFloat2ᚖfloat64(ctx context.Context, v interface{}) (*float64, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalOFloat2float64(ctx, v) + return &res, err +} + +func (ec *executionContext) marshalOFloat2ᚖfloat64(ctx context.Context, sel ast.SelectionSet, v *float64) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec.marshalOFloat2float64(ctx, sel, *v) +} + func (ec *executionContext) unmarshalOID2string(ctx context.Context, v interface{}) (string, error) { return graphql.UnmarshalID(v) } @@ -18416,13 +18712,6 @@ func (ec *executionContext) marshalOProposal2ᚖcodeᚗvegaprotocolᚗioᚋvega return ec._Proposal(ctx, sel, v) } -func (ec *executionContext) marshalOProposalChange2codeᚗvegaprotocolᚗioᚋvegaᚋgatewayᚋgraphqlᚐProposalChange(ctx context.Context, sel ast.SelectionSet, v ProposalChange) graphql.Marshaler { - if v == nil { - return graphql.Null - } - return ec._ProposalChange(ctx, sel, v) -} - func (ec *executionContext) unmarshalOProposalState2codeᚗvegaprotocolᚗioᚋvegaᚋgatewayᚋgraphqlᚐProposalState(ctx context.Context, v interface{}) (ProposalState, error) { var res ProposalState return res, res.UnmarshalGQL(v) diff --git a/gateway/graphql/helpers.go b/gateway/graphql/helpers.go index 13b55463ac7..6ba31b0dd13 100644 --- a/gateway/graphql/helpers.go +++ b/gateway/graphql/helpers.go @@ -19,83 +19,6 @@ func safeStringUint64(input string) (uint64, error) { return 0, fmt.Errorf("invalid input string for uint64 conversion %s", input) } -func convertInterval(interval Interval) (types.Interval, error) { - switch interval { - case IntervalI15m: - return types.Interval_INTERVAL_I15M, nil - case IntervalI1d: - return types.Interval_INTERVAL_I1D, nil - case IntervalI1h: - return types.Interval_INTERVAL_I1H, nil - case IntervalI1m: - return types.Interval_INTERVAL_I1M, nil - case IntervalI5m: - return types.Interval_INTERVAL_I5M, nil - case IntervalI6h: - return types.Interval_INTERVAL_I6H, nil - default: - err := fmt.Errorf("invalid interval when subscribing to candles, falling back to default: I15M, (%v)", interval) - - return types.Interval_INTERVAL_UNSPECIFIED, err - } -} - -func parseOrderTimeInForce(timeInForce OrderTimeInForce) (types.Order_TimeInForce, error) { - switch timeInForce { - case OrderTimeInForceGtc: - return types.Order_TIF_GTC, nil - case OrderTimeInForceGtt: - return types.Order_TIF_GTT, nil - case OrderTimeInForceIoc: - return types.Order_TIF_IOC, nil - case OrderTimeInForceFok: - return types.Order_TIF_FOK, nil - default: - return types.Order_TIF_GTC, fmt.Errorf("unknown type: %s", timeInForce.String()) - } -} - -func parseOrderType(ty OrderType) (types.Order_Type, error) { - switch ty { - case OrderTypeLimit: - return types.Order_TYPE_LIMIT, nil - case OrderTypeMarket: - return types.Order_TYPE_MARKET, nil - default: - // handle types.Order_TYPE_NETWORK as an error here, as we do not expected - // it to be set by through the API, only by the core internally - return 0, fmt.Errorf("unknown type: %s", ty.String()) - } -} - -func parseOrderStatus(orderStatus *OrderStatus) (types.Order_Status, error) { - switch *orderStatus { - case OrderStatusActive: - return types.Order_STATUS_ACTIVE, nil - case OrderStatusExpired: - return types.Order_STATUS_EXPIRED, nil - case OrderStatusCancelled: - return types.Order_STATUS_CANCELLED, nil - case OrderStatusFilled: - return types.Order_STATUS_FILLED, nil - case OrderStatusRejected: - return types.Order_STATUS_REJECTED, nil - default: - return types.Order_STATUS_INVALID, fmt.Errorf("unknown status: %s", orderStatus.String()) - } -} - -func parseSide(side *Side) (types.Side, error) { - switch *side { - case SideBuy: - return types.Side_SIDE_BUY, nil - case SideSell: - return types.Side_SIDE_SELL, nil - default: - return types.Side_SIDE_BUY, fmt.Errorf("unknown side: %s", side.String()) - } -} - // customErrorFromStatus provides a richer error experience from grpc ErrorDetails // which is provided by the Vega grpc API. This helper takes in the error provided // by a grpc client and either returns a custom graphql error or the raw error string. diff --git a/gateway/graphql/helpers_enum.go b/gateway/graphql/helpers_enum.go new file mode 100644 index 00000000000..1f85067efe4 --- /dev/null +++ b/gateway/graphql/helpers_enum.go @@ -0,0 +1,395 @@ +package gql + +import ( + "fmt" + + types "code.vegaprotocol.io/vega/proto" +) + +// convertAccountTypeToProto converts a GraphQL enum to a Proto enum +func convertAccountTypeToProto(x AccountType) (types.AccountType, error) { + switch x { + case AccountTypeGeneral: + return types.AccountType_ACCOUNT_TYPE_GENERAL, nil + case AccountTypeInsurance: + return types.AccountType_ACCOUNT_TYPE_INSURANCE, nil + case AccountTypeMargin: + return types.AccountType_ACCOUNT_TYPE_MARGIN, nil + case AccountTypeSettlement: + return types.AccountType_ACCOUNT_TYPE_SETTLEMENT, nil + default: + err := fmt.Errorf("failed to convert AccountType from GraphQL to Proto: %v", x) + return types.AccountType_ACCOUNT_TYPE_UNSPECIFIED, err + } +} + +// convertAccountTypeFromProto converts a Proto enum to a GraphQL enum +func convertAccountTypeFromProto(x types.AccountType) (AccountType, error) { + switch x { + case types.AccountType_ACCOUNT_TYPE_GENERAL: + return AccountTypeGeneral, nil + case types.AccountType_ACCOUNT_TYPE_INSURANCE: + return AccountTypeInsurance, nil + case types.AccountType_ACCOUNT_TYPE_MARGIN: + return AccountTypeMargin, nil + case types.AccountType_ACCOUNT_TYPE_SETTLEMENT: + return AccountTypeSettlement, nil + default: + err := fmt.Errorf("failed to convert AccountType from Proto to GraphQL: %v", x) + return AccountTypeGeneral, err + } +} + +// convertIntervalToProto converts a GraphQL enum to a Proto enum +func convertIntervalToProto(x Interval) (types.Interval, error) { + switch x { + case IntervalI1m: + return types.Interval_INTERVAL_I1M, nil + case IntervalI5m: + return types.Interval_INTERVAL_I5M, nil + case IntervalI15m: + return types.Interval_INTERVAL_I15M, nil + case IntervalI1h: + return types.Interval_INTERVAL_I1H, nil + case IntervalI6h: + return types.Interval_INTERVAL_I6H, nil + case IntervalI1d: + return types.Interval_INTERVAL_I1D, nil + default: + err := fmt.Errorf("failed to convert Interval from GraphQL to Proto: %v", x) + return types.Interval_INTERVAL_UNSPECIFIED, err + } +} + +// convertIntervalFromProto converts a Proto enum to a GraphQL enum +func convertIntervalFromProto(x types.Interval) (Interval, error) { + switch x { + case types.Interval_INTERVAL_I1M: + return IntervalI1m, nil + case types.Interval_INTERVAL_I5M: + return IntervalI5m, nil + case types.Interval_INTERVAL_I15M: + return IntervalI15m, nil + case types.Interval_INTERVAL_I1H: + return IntervalI1h, nil + case types.Interval_INTERVAL_I6H: + return IntervalI6h, nil + case types.Interval_INTERVAL_I1D: + return IntervalI1d, nil + default: + err := fmt.Errorf("failed to convert Interval from Proto to GraphQL: %v", x) + return IntervalI15m, err + } +} + +// convertOrderStatusToProto converts a GraphQL enum to a Proto enum +func convertOrderStatusToProto(x OrderStatus) (types.Order_Status, error) { + switch x { + case OrderStatusActive: + return types.Order_STATUS_ACTIVE, nil + case OrderStatusExpired: + return types.Order_STATUS_EXPIRED, nil + case OrderStatusCancelled: + return types.Order_STATUS_CANCELLED, nil + case OrderStatusStopped: + return types.Order_STATUS_STOPPED, nil + case OrderStatusFilled: + return types.Order_STATUS_FILLED, nil + case OrderStatusRejected: + return types.Order_STATUS_REJECTED, nil + case OrderStatusPartiallyFilled: + return types.Order_STATUS_PARTIALLY_FILLED, nil + default: + err := fmt.Errorf("failed to convert OrderStatus from GraphQL to Proto: %v", x) + return types.Order_STATUS_INVALID, err + } +} + +// convertOrderStatusFromProto converts a Proto enum to a GraphQL enum +func convertOrderStatusFromProto(x types.Order_Status) (OrderStatus, error) { + switch x { + case types.Order_STATUS_ACTIVE: + return OrderStatusActive, nil + case types.Order_STATUS_EXPIRED: + return OrderStatusExpired, nil + case types.Order_STATUS_CANCELLED: + return OrderStatusCancelled, nil + case types.Order_STATUS_STOPPED: + return OrderStatusStopped, nil + case types.Order_STATUS_FILLED: + return OrderStatusFilled, nil + case types.Order_STATUS_REJECTED: + return OrderStatusRejected, nil + case types.Order_STATUS_PARTIALLY_FILLED: + return OrderStatusPartiallyFilled, nil + default: + err := fmt.Errorf("failed to convert OrderStatus from Proto to GraphQL: %v", x) + return OrderStatusActive, err + } +} + +// convertOrderTypeToProto converts a GraphQL enum to a Proto enum +func convertOrderTypeToProto(x OrderType) (types.Order_Type, error) { + switch x { + case OrderTypeLimit: + return types.Order_TYPE_LIMIT, nil + case OrderTypeMarket: + return types.Order_TYPE_MARKET, nil + case OrderTypeNetwork: + return types.Order_TYPE_NETWORK, nil + default: + err := fmt.Errorf("failed to convert OrderType from GraphQL to Proto: %v", x) + return types.Order_TYPE_UNSPECIFIED, err + } +} + +// convertOrderTypeFromProto converts a Proto enum to a GraphQL enum +func convertOrderTypeFromProto(x types.Order_Type) (OrderType, error) { + switch x { + case types.Order_TYPE_LIMIT: + return OrderTypeLimit, nil + case types.Order_TYPE_MARKET: + return OrderTypeMarket, nil + case types.Order_TYPE_NETWORK: + return OrderTypeNetwork, nil + default: + err := fmt.Errorf("failed to convert OrderType from Proto to GraphQL: %v", x) + return OrderTypeLimit, err + } +} + +// convertProposalStateToProto converts a GraphQL enum to a Proto enum +func convertProposalStateToProto(x ProposalState) (types.Proposal_State, error) { + switch x { + case ProposalStateFailed: + return types.Proposal_STATE_FAILED, nil + case ProposalStateOpen: + return types.Proposal_STATE_OPEN, nil + case ProposalStatePassed: + return types.Proposal_STATE_PASSED, nil + case ProposalStateRejected: + return types.Proposal_STATE_REJECTED, nil + case ProposalStateDeclined: + return types.Proposal_STATE_DECLINED, nil + case ProposalStateEnacted: + return types.Proposal_STATE_ENACTED, nil + default: + err := fmt.Errorf("failed to convert ProposalState from GraphQL to Proto: %v", x) + return types.Proposal_STATE_UNSPECIFIED, err + } +} + +// convertProposalStateFromProto converts a Proto enum to a GraphQL enum +func convertProposalStateFromProto(x types.Proposal_State) (ProposalState, error) { + switch x { + case types.Proposal_STATE_FAILED: + return ProposalStateFailed, nil + case types.Proposal_STATE_OPEN: + return ProposalStateOpen, nil + case types.Proposal_STATE_PASSED: + return ProposalStatePassed, nil + case types.Proposal_STATE_REJECTED: + return ProposalStateRejected, nil + case types.Proposal_STATE_DECLINED: + return ProposalStateDeclined, nil + case types.Proposal_STATE_ENACTED: + return ProposalStateEnacted, nil + default: + err := fmt.Errorf("failed to convert ProposalState from Proto to GraphQL: %v", x) + return ProposalStateFailed, err + } +} + +// convertRejectionReasonToProto converts a GraphQL enum to a Proto enum +func convertRejectionReasonToProto(x RejectionReason) (types.OrderError, error) { + switch x { + case RejectionReasonInvalidMarketID: + return types.OrderError_ORDER_ERROR_INVALID_MARKET_ID, nil + case RejectionReasonInvalidOrderID: + return types.OrderError_ORDER_ERROR_INVALID_ORDER_ID, nil + case RejectionReasonOrderOutOfSequence: + return types.OrderError_ORDER_ERROR_OUT_OF_SEQUENCE, nil + case RejectionReasonInvalidRemainingSize: + return types.OrderError_ORDER_ERROR_INVALID_REMAINING_SIZE, nil + case RejectionReasonTimeFailure: + return types.OrderError_ORDER_ERROR_TIME_FAILURE, nil + case RejectionReasonOrderRemovalFailure: + return types.OrderError_ORDER_ERROR_REMOVAL_FAILURE, nil + case RejectionReasonInvalidExpirationTime: + return types.OrderError_ORDER_ERROR_INVALID_EXPIRATION_DATETIME, nil + case RejectionReasonInvalidOrderReference: + return types.OrderError_ORDER_ERROR_INVALID_ORDER_REFERENCE, nil + case RejectionReasonEditNotAllowed: + return types.OrderError_ORDER_ERROR_EDIT_NOT_ALLOWED, nil + case RejectionReasonOrderAmendFailure: + return types.OrderError_ORDER_ERROR_AMEND_FAILURE, nil + case RejectionReasonOrderNotFound: + return types.OrderError_ORDER_ERROR_NOT_FOUND, nil + case RejectionReasonInvalidPartyID: + return types.OrderError_ORDER_ERROR_INVALID_PARTY_ID, nil + case RejectionReasonMarketClosed: + return types.OrderError_ORDER_ERROR_MARKET_CLOSED, nil + case RejectionReasonMarginCheckFailed: + return types.OrderError_ORDER_ERROR_MARGIN_CHECK_FAILED, nil + case RejectionReasonInternalError: + return types.OrderError_ORDER_ERROR_INTERNAL_ERROR, nil + default: + err := fmt.Errorf("failed to convert RejectionReason from GraphQL to Proto: %v", x) + return types.OrderError_ORDER_ERROR_INTERNAL_ERROR, err + } +} + +// convertRejectionReasonFromProto converts a Proto enum to a GraphQL enum +func convertRejectionReasonFromProto(x types.OrderError) (RejectionReason, error) { + switch x { + case types.OrderError_ORDER_ERROR_INVALID_MARKET_ID: + return RejectionReasonInvalidMarketID, nil + case types.OrderError_ORDER_ERROR_INVALID_ORDER_ID: + return RejectionReasonInvalidOrderID, nil + case types.OrderError_ORDER_ERROR_OUT_OF_SEQUENCE: + return RejectionReasonOrderOutOfSequence, nil + case types.OrderError_ORDER_ERROR_INVALID_REMAINING_SIZE: + return RejectionReasonInvalidRemainingSize, nil + case types.OrderError_ORDER_ERROR_TIME_FAILURE: + return RejectionReasonTimeFailure, nil + case types.OrderError_ORDER_ERROR_REMOVAL_FAILURE: + return RejectionReasonOrderRemovalFailure, nil + case types.OrderError_ORDER_ERROR_INVALID_EXPIRATION_DATETIME: + return RejectionReasonInvalidExpirationTime, nil + case types.OrderError_ORDER_ERROR_INVALID_ORDER_REFERENCE: + return RejectionReasonInvalidOrderReference, nil + case types.OrderError_ORDER_ERROR_EDIT_NOT_ALLOWED: + return RejectionReasonEditNotAllowed, nil + case types.OrderError_ORDER_ERROR_AMEND_FAILURE: + return RejectionReasonOrderAmendFailure, nil + case types.OrderError_ORDER_ERROR_NOT_FOUND: + return RejectionReasonOrderNotFound, nil + case types.OrderError_ORDER_ERROR_INVALID_PARTY_ID: + return RejectionReasonInvalidPartyID, nil + case types.OrderError_ORDER_ERROR_MARKET_CLOSED: + return RejectionReasonMarketClosed, nil + case types.OrderError_ORDER_ERROR_MARGIN_CHECK_FAILED: + return RejectionReasonMarginCheckFailed, nil + case types.OrderError_ORDER_ERROR_INTERNAL_ERROR: + return RejectionReasonInternalError, nil + default: + err := fmt.Errorf("failed to convert RejectionReason from Proto to GraphQL: %v", x) + return RejectionReasonInternalError, err + } +} + +// convertSideToProto converts a GraphQL enum to a Proto enum +func convertSideToProto(x Side) (types.Side, error) { + switch x { + case SideBuy: + return types.Side_SIDE_BUY, nil + case SideSell: + return types.Side_SIDE_SELL, nil + default: + err := fmt.Errorf("failed to convert Side from GraphQL to Proto: %v", x) + return types.Side_SIDE_UNSPECIFIED, err + } +} + +// convertSideFromProto converts a Proto enum to a GraphQL enum +func convertSideFromProto(x types.Side) (Side, error) { + switch x { + case types.Side_SIDE_BUY: + return SideBuy, nil + case types.Side_SIDE_SELL: + return SideSell, nil + default: + err := fmt.Errorf("failed to convert Side from Proto to GraphQL: %v", x) + return SideBuy, err + } +} + +// convertOrderTimeInForceToProto converts a GraphQL enum to a Proto enum +func convertOrderTimeInForceToProto(x OrderTimeInForce) (types.Order_TimeInForce, error) { + switch x { + case OrderTimeInForceFok: + return types.Order_TIF_FOK, nil + case OrderTimeInForceIoc: + return types.Order_TIF_IOC, nil + case OrderTimeInForceGtc: + return types.Order_TIF_GTC, nil + case OrderTimeInForceGtt: + return types.Order_TIF_GTT, nil + default: + err := fmt.Errorf("failed to convert OrderTimeInForce from GraphQL to Proto: %v", x) + return types.Order_TIF_UNSPECIFIED, err + } +} + +// convertOrderTimeInForceFromProto converts a Proto enum to a GraphQL enum +func convertOrderTimeInForceFromProto(x types.Order_TimeInForce) (OrderTimeInForce, error) { + switch x { + case types.Order_TIF_FOK: + return OrderTimeInForceFok, nil + case types.Order_TIF_IOC: + return OrderTimeInForceIoc, nil + case types.Order_TIF_GTC: + return OrderTimeInForceGtc, nil + case types.Order_TIF_GTT: + return OrderTimeInForceGtt, nil + default: + err := fmt.Errorf("failed to convert OrderTimeInForce from Proto to GraphQL: %v", x) + return OrderTimeInForceGtc, err + } +} + +// convertTradeTypeToProto converts a GraphQL enum to a Proto enum +func convertTradeTypeToProto(x TradeType) (types.Trade_Type, error) { + switch x { + case TradeTypeDefault: + return types.Trade_TYPE_DEFAULT, nil + case TradeTypeNetworkCloseOutBad: + return types.Trade_TYPE_NETWORK_CLOSE_OUT_BAD, nil + case TradeTypeNetworkCloseOutGood: + return types.Trade_TYPE_NETWORK_CLOSE_OUT_GOOD, nil + default: + err := fmt.Errorf("failed to convert TradeType from GraphQL to Proto: %v", x) + return types.Trade_TYPE_UNSPECIFIED, err + } +} + +// convertTradeTypeFromProto converts a Proto enum to a GraphQL enum +func convertTradeTypeFromProto(x types.Trade_Type) (TradeType, error) { + switch x { + case types.Trade_TYPE_DEFAULT: + return TradeTypeDefault, nil + case types.Trade_TYPE_NETWORK_CLOSE_OUT_BAD: + return TradeTypeNetworkCloseOutBad, nil + case types.Trade_TYPE_NETWORK_CLOSE_OUT_GOOD: + return TradeTypeNetworkCloseOutGood, nil + default: + err := fmt.Errorf("failed to convert TradeType from Proto to GraphQL: %v", x) + return TradeTypeDefault, err + } +} + +// convertVoteValueToProto converts a GraphQL enum to a Proto enum +func convertVoteValueToProto(x VoteValue) (types.Vote_Value, error) { + switch x { + case VoteValueNo: + return types.Vote_VALUE_NO, nil + case VoteValueYes: + return types.Vote_VALUE_YES, nil + default: + err := fmt.Errorf("failed to convert VoteValue from GraphQL to Proto: %v", x) + return types.Vote_VALUE_UNSPECIFIED, err + } +} + +// convertVoteValueFromProto converts a Proto enum to a GraphQL enum +func convertVoteValueFromProto(x types.Vote_Value) (VoteValue, error) { + switch x { + case types.Vote_VALUE_NO: + return VoteValueNo, nil + case types.Vote_VALUE_YES: + return VoteValueYes, nil + default: + err := fmt.Errorf("failed to convert VoteValue from Proto to GraphQL: %v", x) + return VoteValueNo, err + } +} diff --git a/gateway/graphql/helpers_test.go b/gateway/graphql/helpers_test.go index a1c8f2974ec..e162b40d42f 100644 --- a/gateway/graphql/helpers_test.go +++ b/gateway/graphql/helpers_test.go @@ -40,56 +40,56 @@ func TestSafeStringUint64(t *testing.T) { func TestParseOrderStatus(t *testing.T) { active := OrderStatusActive - status, err := parseOrderStatus(&active) + status, err := convertOrderStatusToProto(active) assert.Nil(t, err) assert.Equal(t, types.Order_STATUS_ACTIVE, status) expired := OrderStatusExpired - status, err = parseOrderStatus(&expired) + status, err = convertOrderStatusToProto(expired) assert.Nil(t, err) assert.Equal(t, types.Order_STATUS_EXPIRED, status) cancelled := OrderStatusCancelled - status, err = parseOrderStatus(&cancelled) + status, err = convertOrderStatusToProto(cancelled) assert.Nil(t, err) assert.Equal(t, types.Order_STATUS_CANCELLED, status) unknown := OrderStatus("好候") - _, err = parseOrderStatus(&unknown) + _, err = convertOrderStatusToProto(unknown) assert.Error(t, err) } func TestParseOrderTimeInForce(t *testing.T) { fok := OrderTimeInForceFok - orderType, err := parseOrderTimeInForce(fok) + orderType, err := convertOrderTimeInForceToProto(fok) assert.Nil(t, err) assert.Equal(t, types.Order_TIF_FOK, orderType) ioc := OrderTimeInForceIoc - orderType, err = parseOrderTimeInForce(ioc) + orderType, err = convertOrderTimeInForceToProto(ioc) assert.Nil(t, err) assert.Equal(t, types.Order_TIF_IOC, orderType) gtt := OrderTimeInForceGtt - orderType, err = parseOrderTimeInForce(gtt) + orderType, err = convertOrderTimeInForceToProto(gtt) assert.Nil(t, err) assert.Equal(t, types.Order_TIF_GTT, orderType) gtc := OrderTimeInForceGtc - orderType, err = parseOrderTimeInForce(gtc) + orderType, err = convertOrderTimeInForceToProto(gtc) assert.Nil(t, err) assert.Equal(t, types.Order_TIF_GTC, orderType) unknown := OrderTimeInForce("好到时候") - _, err = parseOrderTimeInForce(unknown) + _, err = convertOrderTimeInForceToProto(unknown) assert.Error(t, err) } func TestParseSide(t *testing.T) { buy := SideBuy - side, err := parseSide(&buy) + side, err := convertSideToProto(buy) assert.Nil(t, err) assert.Equal(t, types.Side_SIDE_BUY, side) sell := SideSell - side, err = parseSide(&sell) + side, err = convertSideToProto(sell) assert.Nil(t, err) assert.Equal(t, types.Side_SIDE_SELL, side) unknown := Side("好到时候") - _, err = parseSide(&unknown) + _, err = convertSideToProto(unknown) assert.Error(t, err) } diff --git a/gateway/graphql/modelext.go b/gateway/graphql/modelext.go index a9736127250..90d6545a02d 100644 --- a/gateway/graphql/modelext.go +++ b/gateway/graphql/modelext.go @@ -1,9 +1,6 @@ package gql import ( - "math" - "strings" - types "code.vegaprotocol.io/vega/proto" protoapi "code.vegaprotocol.io/vega/proto/api" "github.com/pkg/errors" @@ -42,12 +39,10 @@ var ( ErrNilDiscreteTradingDuration = errors.New("nil discrete trading duration") // ErrNilContinuousTradingTickSize ... ErrNilContinuousTradingTickSize = errors.New("nil continuous trading tick-size") - // ErrnilScalingFactors... + // ErrNilScalingFactors ... ErrNilScalingFactors = errors.New("nil scaling factors") - // ErrNilMarginCalculator + // ErrNilMarginCalculator ... ErrNilMarginCalculator = errors.New("nil margin calculator") - // ErrParticipationStake ... - ErrParticipationStake = errors.New("minimum participation stake contains too large value") // ErrInvalidTickSize ... ErrInvalidTickSize = errors.New("invalid tick size") // ErrInvalidDecimalPlaces ... @@ -509,21 +504,15 @@ func MarketFromProto(pmkt *types.Market) (*Market, error) { // IntoProto ... func (a AccountType) IntoProto() types.AccountType { - if !a.IsValid() { - return types.AccountType_ACCOUNT_TYPE_UNSPECIFIED - } - return types.AccountType(types.AccountType_value[strings.ToUpper(string(a))]) + at, _ := convertAccountTypeToProto(a) + return at } // ProposalTermsFromProto ... func ProposalTermsFromProto(terms *types.ProposalTerms) (*ProposalTerms, error) { - if terms.MinParticipationStake > math.MaxInt32 { - return nil, ErrParticipationStake - } result := &ProposalTerms{ - ClosingDatetime: secondsTSToDatetime(terms.ClosingTimestamp), - EnactmentDatetime: secondsTSToDatetime(terms.EnactmentTimestamp), - MinParticipationStake: int(terms.MinParticipationStake), + ClosingDatetime: secondsTSToDatetime(terms.ClosingTimestamp), + EnactmentDatetime: secondsTSToDatetime(terms.EnactmentTimestamp), } if terms.GetUpdateMarket() != nil { result.Change = nil @@ -707,9 +696,8 @@ func (p ProposalTermsInput) IntoProto() (*types.ProposalTerms, error) { } result := &types.ProposalTerms{ - ClosingTimestamp: closing, - EnactmentTimestamp: enactment, - MinParticipationStake: uint64(p.MinParticipationStake), + ClosingTimestamp: closing, + EnactmentTimestamp: enactment, } if p.UpdateMarket != nil { result.Change = &types.ProposalTerms_UpdateMarket{} @@ -748,56 +736,16 @@ func (s *ProposalState) ToOptionalProposalState() (*protoapi.OptionalProposalSta // IntoProtoValue ... func (s ProposalState) IntoProtoValue() (types.Proposal_State, error) { - switch s { - case ProposalStateFailed: - return types.Proposal_STATE_FAILED, nil - case ProposalStateOpen: - return types.Proposal_STATE_OPEN, nil - case ProposalStatePassed: - return types.Proposal_STATE_PASSED, nil - case ProposalStateDeclined: - return types.Proposal_STATE_DECLINED, nil - case ProposalStateRejected: - return types.Proposal_STATE_REJECTED, nil - case ProposalStateEnacted: - return types.Proposal_STATE_ENACTED, nil - } - return types.Proposal_State(-1), ErrInvalidProposalState -} - -// ProposalStateFromProto ... -func ProposalStateFromProto(state types.Proposal_State) (ProposalState, error) { - switch state { - case types.Proposal_STATE_FAILED: - return ProposalStateFailed, nil - case types.Proposal_STATE_OPEN: - return ProposalStateOpen, nil - case types.Proposal_STATE_PASSED: - return ProposalStatePassed, nil - case types.Proposal_STATE_DECLINED: - return ProposalStateDeclined, nil - case types.Proposal_STATE_REJECTED: - return ProposalStateRejected, nil - case types.Proposal_STATE_ENACTED: - return ProposalStateEnacted, nil - } - return ProposalState(""), ErrInvalidProposalState -} - -// VoteValueFromProto ... -func VoteValueFromProto(v types.Vote_Value) VoteValue { - if v == types.Vote_VALUE_YES { - return VoteValueYes - } - return VoteValueNo + return convertProposalStateToProto(s) } // ProposalVoteFromProto ... func ProposalVoteFromProto(v *types.Vote, caster *types.Party) *ProposalVote { + value, _ := convertVoteValueFromProto(v.Value) return &ProposalVote{ Vote: &Vote{ Party: caster, - Value: VoteValueFromProto(v.Value), + Value: value, Datetime: nanoTSToDatetime(v.Timestamp), }, ProposalID: v.ProposalID, diff --git a/gateway/graphql/modelext_test.go b/gateway/graphql/modelext_test.go index 1746654e478..bae954201b4 100644 --- a/gateway/graphql/modelext_test.go +++ b/gateway/graphql/modelext_test.go @@ -1,7 +1,6 @@ package gql_test import ( - "math" "testing" gql "code.vegaprotocol.io/vega/gateway/graphql" @@ -511,14 +510,13 @@ func TestModelConverters(t *testing.T) { t.Run("ProposalTermsInput.IntoProto nil change", func(t *testing.T) { proposal := &gql.ProposalTermsInput{ - ClosingDatetime: "2020-09-30T07:28:06+00:00", - EnactmentDatetime: "2020-10-30T07:28:06+00:00", - MinParticipationStake: 10, + ClosingDatetime: "2020-09-30T07:28:06+00:00", + EnactmentDatetime: "2020-10-30T07:28:06+00:00", } proposalProto, err := proposal.IntoProto() assert.Nil(t, proposalProto) assert.Error(t, err) - assert.Equal(t, gql.ErrInvalidChange, err) + assert.EqualError(t, gql.ErrInvalidChange, err.Error()) }) t.Run("ProposalTermsInput.IntoProto", func(t *testing.T) { @@ -574,9 +572,8 @@ func TestModelConverters(t *testing.T) { assert.Nil(t, err) proposal := &gql.ProposalTermsInput{ - ClosingDatetime: "2020-09-30T07:28:06+00:00", - EnactmentDatetime: "2020-10-30T07:28:06+00:00", - MinParticipationStake: 10, + ClosingDatetime: "2020-09-30T07:28:06+00:00", + EnactmentDatetime: "2020-10-30T07:28:06+00:00", NewMarket: &gql.NewMarketInput{ Market: &mkt, }, @@ -586,19 +583,7 @@ func TestModelConverters(t *testing.T) { assert.NoError(t, err) }) - t.Run("ProposalTermsFromProto invalid stake", func(t *testing.T) { - terms := &proto.ProposalTerms{ - ClosingTimestamp: 1234567, - EnactmentTimestamp: 1234568, - MinParticipationStake: math.MaxInt32 * 2, - } - protoTerms, err := gql.ProposalTermsFromProto(terms) - assert.Nil(t, protoTerms) - assert.Error(t, err) - assert.Equal(t, gql.ErrParticipationStake, err) - }) - - t.Run("ProposalTermsFromProto invalid stake", func(t *testing.T) { + t.Run("ProposalTermsFromProto valid data", func(t *testing.T) { pm := &proto.Market{ TradableInstrument: &proto.TradableInstrument{ Instrument: &proto.Instrument{ @@ -638,9 +623,8 @@ func TestModelConverters(t *testing.T) { } terms := &proto.ProposalTerms{ - ClosingTimestamp: 1234567, - EnactmentTimestamp: 1234568, - MinParticipationStake: 10, + ClosingTimestamp: 1234567, + EnactmentTimestamp: 1234568, Change: &proto.ProposalTerms_NewMarket{ NewMarket: &proto.NewMarket{ Changes: pm, diff --git a/gateway/graphql/models.go b/gateway/graphql/models.go index 381755cfe7c..8238b4e25f7 100644 --- a/gateway/graphql/models.go +++ b/gateway/graphql/models.go @@ -282,28 +282,34 @@ type PreparedVote struct { type ProposalTerms struct { // ISO-8601 time and date when voting closes for this proposal. + // Constrained by "minCloseInSeconds" and "maxCloseInSeconds" network parameters. ClosingDatetime string `json:"closingDatetime"` // ISO-8601 time and date when this proposal is executed (if passed). Note that it has to be after closing date time. + // Constrained by "minEnactInSeconds" and "maxEnactInSeconds" network parameters. EnactmentDatetime string `json:"enactmentDatetime"` - // Minimum participation stake required for this proposal to pass - MinParticipationStake int `json:"minParticipationStake"` - // Actual change being introduced by the proposal + // Actual change being introduced by the proposal - action the proposal triggers if passed and enacted. Change ProposalChange `json:"change"` } // Proposal terms input. Only one kind of change is expected. Proposals with no changes or more than one will not be accepted. type ProposalTermsInput struct { // ISO-8601 time and date when voting closes for this proposal. + // Constrained by "minCloseInSeconds" and "maxCloseInSeconds" network parameters. ClosingDatetime string `json:"closingDatetime"` // ISO-8601 time and date when this proposal is executed (if passed). Note that it has to be after closing date time. + // Constrained by "minEnactInSeconds" and "maxEnactInSeconds" network parameters. EnactmentDatetime string `json:"enactmentDatetime"` - // Minimum participation stake required for this proposal to pass - MinParticipationStake int `json:"minParticipationStake"` - // Optional field to define update market change. If this is set along with another change, proposal will not be accepted. - UpdateMarket *UpdateMarketInput `json:"updateMarket"` - // Optional field to define new market change. If this is set along with another change, proposal will not be accepted. + // Field defining new market change - the proposal will create new market if passed and enacted. + // It can only be set if "updateMarket" and "updateNetwork" are not set (the proposal will be rejected otherwise). + // One of "newMarket", "updateMarket", "updateNetwork" must be set (the proposal will be rejected otherwise). NewMarket *NewMarketInput `json:"newMarket"` - // Optional field to define an update of network parameters. If this is set along with another change, proposal will not be accepted. + // Field defining update market change - the proposal will update existing market if passed and enacted. + // It can only be set if "newMarket" and "updateNetwork" are not set (the proposal will be rejected otherwise). + // One of "newMarket", "updateMarket", "updateNetwork" must be set (the proposal will be rejected otherwise). + UpdateMarket *UpdateMarketInput `json:"updateMarket"` + // Field defining update network change - the proposal will update Vega network parameters if passed and enacted. + // It can only be set if "newMarket" and "updateMarket" are not set (the proposal will be rejected otherwise). + // One of "newMarket", "updateMarket", "updateNetwork" must be set (the proposal will be rejected otherwise). UpdateNetwork *UpdateNetworkInput `json:"updateNetwork"` } @@ -410,9 +416,18 @@ type UpdateNetwork struct { // can be set to be executed (if that proposal passed). // Value represents duration in seconds. MaxEnactInSeconds *int `json:"maxEnactInSeconds"` - // Network parameter that restricts the minimum participation stake - // required for a proposal to pass. - MinParticipationStake *int `json:"minParticipationStake"` + // Network parameter that sets participation level required for any proposal to pass. + // Value from 0 to 1. + RequiredParticipation *float64 `json:"requiredParticipation"` + // Network parameter that sets majority level required for any proposal to pass. + // Value from 0.5 to 1. + RequiredMajority *float64 `json:"requiredMajority"` + // Network parameter that sets minimum balance required for a party + // to be able to submit a new proposal. Value greater than 0 to 1. + MinProposerBalance *float64 `json:"minProposerBalance"` + // Network parameter that sets minimum balance required for a party + // to be able to cast a vote. Value greater than 0 to 1. + MinVoterBalance *float64 `json:"minVoterBalance"` } func (UpdateNetwork) IsProposalChange() {} @@ -433,9 +448,18 @@ type UpdateNetworkInput struct { // can be set to be executed (if that proposal passed). // Value represents duration in seconds. MaxEnactInSeconds *int `json:"maxEnactInSeconds"` - // Network parameter that restricts the minimum participation stake - // required for a proposal to pass. - MinParticipationStake *int `json:"minParticipationStake"` + // Network parameter that sets participation level required for any proposal to pass. + // Value from 0 to 1. + RequiredParticipation *float64 `json:"requiredParticipation"` + // Network parameter that sets majority level required for any proposal to pass. + // Value from 0.5 to 1. + RequiredMajority *float64 `json:"requiredMajority"` + // Network parameter that sets minimum balance required for a party + // to be able to submit a new proposal. Value greater than 0 to 1. + MinProposerBalance *float64 `json:"minProposerBalance"` + // Network parameter that sets minimum balance required for a party + // to be able to cast a vote. Value greater than 0 to 1. + MinVoterBalance *float64 `json:"minVoterBalance"` } type Vote struct { @@ -560,30 +584,33 @@ const ( // The order is active and not cancelled or expired, it could be unfilled, partially filled or fully filled. // Active does not necessarily mean it's still on the order book. OrderStatusActive OrderStatus = "Active" - // The order is cancelled, the order could be partially filled or unfilled before it was cancelled. It is not possible to cancel an order with 0 remaining. - OrderStatusCancelled OrderStatus = "Cancelled" // This order trades any amount and as much as possible and remains on the book until it either trades completely or expires. OrderStatusExpired OrderStatus = "Expired" + // The order is cancelled, the order could be partially filled or unfilled before it was cancelled. It is not possible to cancel an order with 0 remaining. + OrderStatusCancelled OrderStatus = "Cancelled" // This order was of type IOC or FOK and could not be processed by the matching engine due to lack of liquidity. OrderStatusStopped OrderStatus = "Stopped" // This order is fully filled with remaining equals zero. OrderStatusFilled OrderStatus = "Filled" // This order was rejected while beeing processed in the core. OrderStatusRejected OrderStatus = "Rejected" + // This order was partially filled. + OrderStatusPartiallyFilled OrderStatus = "PartiallyFilled" ) var AllOrderStatus = []OrderStatus{ OrderStatusActive, - OrderStatusCancelled, OrderStatusExpired, + OrderStatusCancelled, OrderStatusStopped, OrderStatusFilled, OrderStatusRejected, + OrderStatusPartiallyFilled, } func (e OrderStatus) IsValid() bool { switch e { - case OrderStatusActive, OrderStatusCancelled, OrderStatusExpired, OrderStatusStopped, OrderStatusFilled, OrderStatusRejected: + case OrderStatusActive, OrderStatusExpired, OrderStatusCancelled, OrderStatusStopped, OrderStatusFilled, OrderStatusRejected, OrderStatusPartiallyFilled: return true } return false @@ -800,8 +827,16 @@ const ( RejectionReasonMarketClosed RejectionReason = "MarketClosed" // Margin check failed RejectionReasonMarginCheckFailed RejectionReason = "MarginCheckFailed" + // Order missing general account + RejectionReasonMissingGeneralAccount RejectionReason = "MissingGeneralAccount" // An internal error happend RejectionReasonInternalError RejectionReason = "InternalError" + // Invalid size + RejectionReasonInvalidSize RejectionReason = "InvalidSize" + // Invalid persistence + RejectionReasonInvalidPersistence RejectionReason = "InvalidPersistence" + // Invalid type + RejectionReasonInvalidType RejectionReason = "InvalidType" ) var AllRejectionReason = []RejectionReason{ @@ -819,12 +854,16 @@ var AllRejectionReason = []RejectionReason{ RejectionReasonInvalidPartyID, RejectionReasonMarketClosed, RejectionReasonMarginCheckFailed, + RejectionReasonMissingGeneralAccount, RejectionReasonInternalError, + RejectionReasonInvalidSize, + RejectionReasonInvalidPersistence, + RejectionReasonInvalidType, } func (e RejectionReason) IsValid() bool { switch e { - case RejectionReasonInvalidMarketID, RejectionReasonInvalidOrderID, RejectionReasonOrderOutOfSequence, RejectionReasonInvalidRemainingSize, RejectionReasonTimeFailure, RejectionReasonOrderRemovalFailure, RejectionReasonInvalidExpirationTime, RejectionReasonInvalidOrderReference, RejectionReasonEditNotAllowed, RejectionReasonOrderAmendFailure, RejectionReasonOrderNotFound, RejectionReasonInvalidPartyID, RejectionReasonMarketClosed, RejectionReasonMarginCheckFailed, RejectionReasonInternalError: + case RejectionReasonInvalidMarketID, RejectionReasonInvalidOrderID, RejectionReasonOrderOutOfSequence, RejectionReasonInvalidRemainingSize, RejectionReasonTimeFailure, RejectionReasonOrderRemovalFailure, RejectionReasonInvalidExpirationTime, RejectionReasonInvalidOrderReference, RejectionReasonEditNotAllowed, RejectionReasonOrderAmendFailure, RejectionReasonOrderNotFound, RejectionReasonInvalidPartyID, RejectionReasonMarketClosed, RejectionReasonMarginCheckFailed, RejectionReasonMissingGeneralAccount, RejectionReasonInternalError, RejectionReasonInvalidSize, RejectionReasonInvalidPersistence, RejectionReasonInvalidType: return true } return false @@ -895,6 +934,53 @@ func (e Side) MarshalGQL(w io.Writer) { fmt.Fprint(w, strconv.Quote(e.String())) } +// Valid trade types +type TradeType string + +const ( + // Default trade type + TradeTypeDefault TradeType = "Default" + // Network close-out - good + TradeTypeNetworkCloseOutGood TradeType = "NetworkCloseOutGood" + // Network close-out - bad + TradeTypeNetworkCloseOutBad TradeType = "NetworkCloseOutBad" +) + +var AllTradeType = []TradeType{ + TradeTypeDefault, + TradeTypeNetworkCloseOutGood, + TradeTypeNetworkCloseOutBad, +} + +func (e TradeType) IsValid() bool { + switch e { + case TradeTypeDefault, TradeTypeNetworkCloseOutGood, TradeTypeNetworkCloseOutBad: + return true + } + return false +} + +func (e TradeType) String() string { + return string(e) +} + +func (e *TradeType) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = TradeType(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid TradeType", str) + } + return nil +} + +func (e TradeType) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + type VoteValue string const ( diff --git a/gateway/graphql/resolvers.go b/gateway/graphql/resolvers.go index 7e0f0505a00..fd7073e1ac8 100644 --- a/gateway/graphql/resolvers.go +++ b/gateway/graphql/resolvers.go @@ -278,6 +278,13 @@ func (r *myQueryResolver) Parties(ctx context.Context, name *string) ([]*types.P if err != nil { return nil, err } + + // if we asked for a single party it may be null + // so then we return an empty slice + if party == nil { + return []*types.Party{}, nil + } + return []*types.Party{party}, nil } @@ -511,7 +518,7 @@ func (r *myMarketResolver) Depth(ctx context.Context, market *Market, maxDepth * func (r *myMarketResolver) Candles(ctx context.Context, market *Market, sinceRaw string, interval Interval) ([]*types.Candle, error) { - pinterval, err := convertInterval(interval) + pinterval, err := convertIntervalToProto(interval) if err != nil { r.log.Debug("interval convert error", logging.Error(err)) } @@ -656,10 +663,9 @@ func (r *myPartyResolver) Orders(ctx context.Context, party *types.Party, if len(res.Orders) > 0 { return res.Orders, nil - } else { - // mandatory return field in schema - return []*types.Order{}, nil } + // mandatory return field in schema + return []*types.Order{}, nil } func (r *myPartyResolver) Trades(ctx context.Context, party *types.Party, @@ -685,10 +691,9 @@ func (r *myPartyResolver) Trades(ctx context.Context, party *types.Party, if len(res.Trades) > 0 { return res.Trades, nil - } else { - // mandatory return field in schema - return []*types.Trade{}, nil } + // mandatory return field in schema + return []*types.Trade{}, nil } func (r *myPartyResolver) Positions(ctx context.Context, party *types.Party) ([]*types.Position, error) { @@ -703,25 +708,9 @@ func (r *myPartyResolver) Positions(ctx context.Context, party *types.Party) ([] } if len(res.Positions) > 0 { return res.Positions, nil - } else { - // mandatory return field in schema - return []*types.Position{}, nil - } -} - -func AccountTypeToProto(acc AccountType) (types.AccountType, error) { - switch acc { - case AccountTypeGeneral: - return types.AccountType_ACCOUNT_TYPE_GENERAL, nil - case AccountTypeMargin: - return types.AccountType_ACCOUNT_TYPE_MARGIN, nil - case AccountTypeInsurance: - return types.AccountType_ACCOUNT_TYPE_INSURANCE, nil - case AccountTypeSettlement: - return types.AccountType_ACCOUNT_TYPE_SETTLEMENT, nil - default: - return types.AccountType_ACCOUNT_TYPE_UNSPECIFIED, fmt.Errorf("invalid account type %v, return default (ALL)", acc) } + // mandatory return field in schema + return []*types.Position{}, nil } func (r *myPartyResolver) Accounts(ctx context.Context, party *types.Party, @@ -743,7 +732,7 @@ func (r *myPartyResolver) Accounts(ctx context.Context, party *types.Party, asst = *asset } if accType != nil { - accTy, err = AccountTypeToProto(*accType) + accTy, err = convertAccountTypeToProto(*accType) if err != nil || (accTy != types.AccountType_ACCOUNT_TYPE_GENERAL && accTy != types.AccountType_ACCOUNT_TYPE_MARGIN) { return nil, fmt.Errorf("invalid account type for party %v", accType) } @@ -767,10 +756,9 @@ func (r *myPartyResolver) Accounts(ctx context.Context, party *types.Party, if len(res.Accounts) > 0 { return res.Accounts, nil - } else { - // mandatory return field in schema - return []*types.Account{}, nil } + // mandatory return field in schema + return []*types.Account{}, nil } func (r *myPartyResolver) Proposals(ctx context.Context, party *types.Party, inState *ProposalState) ([]*types.GovernanceData, error) { @@ -838,7 +826,7 @@ func (r *myProposalResolver) State(ctx context.Context, data *types.GovernanceDa if data == nil || data.Proposal == nil { return "", ErrInvalidProposal } - return ProposalStateFromProto(data.Proposal.State) + return convertProposalStateFromProto(data.Proposal.State) } func (r *myProposalResolver) Datetime(ctx context.Context, data *types.GovernanceData) (string, error) { @@ -866,8 +854,12 @@ func (r *myProposalResolver) convertVotes(ctx context.Context, data []*types.Vot if err != nil { return nil, err } + value, err := convertVoteValueFromProto(v.Value) + if err != nil { + return nil, err + } result[i] = &Vote{ - Value: VoteValueFromProto(v.Value), + Value: value, Party: voter, Datetime: nanoTSToDatetime(v.Timestamp), } @@ -1057,48 +1049,11 @@ func (r *myMarketDepthResolver) Market(ctx context.Context, md *types.MarketDept type myOrderResolver VegaResolverRoot -func RejectionReasonFromProtoOrderError(o types.OrderError) (RejectionReason, error) { - switch o { - case types.OrderError_ORDER_ERROR_INVALID_MARKET_ID: - return RejectionReasonInvalidMarketID, nil - case types.OrderError_ORDER_ERROR_INVALID_ORDER_ID: - return RejectionReasonInvalidOrderID, nil - case types.OrderError_ORDER_ERROR_OUT_OF_SEQUENCE: - return RejectionReasonOrderOutOfSequence, nil - case types.OrderError_ORDER_ERROR_INVALID_REMAINING_SIZE: - return RejectionReasonInvalidRemainingSize, nil - case types.OrderError_ORDER_ERROR_TIME_FAILURE: - return RejectionReasonTimeFailure, nil - case types.OrderError_ORDER_ERROR_REMOVAL_FAILURE: - return RejectionReasonOrderRemovalFailure, nil - case types.OrderError_ORDER_ERROR_INVALID_EXPIRATION_DATETIME: - return RejectionReasonInvalidExpirationTime, nil - case types.OrderError_ORDER_ERROR_INVALID_ORDER_REFERENCE: - return RejectionReasonInvalidOrderReference, nil - case types.OrderError_ORDER_ERROR_EDIT_NOT_ALLOWED: - return RejectionReasonEditNotAllowed, nil - case types.OrderError_ORDER_ERROR_AMEND_FAILURE: - return RejectionReasonOrderAmendFailure, nil - case types.OrderError_ORDER_ERROR_NOT_FOUND: - return RejectionReasonOrderNotFound, nil - case types.OrderError_ORDER_ERROR_INVALID_PARTY_ID: - return RejectionReasonInvalidPartyID, nil - case types.OrderError_ORDER_ERROR_MARKET_CLOSED: - return RejectionReasonMarketClosed, nil - case types.OrderError_ORDER_ERROR_MARGIN_CHECK_FAILED: - return RejectionReasonMarginCheckFailed, nil - case types.OrderError_ORDER_ERROR_INTERNAL_ERROR: - return RejectionReasonInternalError, nil - default: - return "", fmt.Errorf("invalid RejectionReason: %v", o) - } -} - func (r *myOrderResolver) RejectionReason(_ context.Context, o *types.Order) (*RejectionReason, error) { if o.Reason == types.OrderError_ORDER_ERROR_NONE { return nil, nil } - reason, err := RejectionReasonFromProtoOrderError(o.Reason) + reason, err := convertRejectionReasonFromProto(o.Reason) if err != nil { return nil, err } @@ -1109,17 +1064,21 @@ func (r *myOrderResolver) Price(ctx context.Context, obj *types.Order) (string, return strconv.FormatUint(obj.Price, 10), nil } func (r *myOrderResolver) TimeInForce(ctx context.Context, obj *types.Order) (OrderTimeInForce, error) { - return OrderTimeInForce(obj.TimeInForce.String()), nil + return convertOrderTimeInForceFromProto(obj.TimeInForce) } func (r *myOrderResolver) Type(ctx context.Context, obj *types.Order) (*OrderType, error) { - t := OrderType(obj.Type.String()) + t, err := convertOrderTypeFromProto(obj.Type) + if err != nil { + return nil, err + } return &t, nil } func (r *myOrderResolver) Side(ctx context.Context, obj *types.Order) (Side, error) { - return Side(obj.Side.String()), nil + return convertSideFromProto(obj.Side) } + func (r *myOrderResolver) Market(ctx context.Context, obj *types.Order) (*Market, error) { if obj == nil { return nil, errors.New("invalid order") @@ -1138,9 +1097,11 @@ func (r *myOrderResolver) Size(ctx context.Context, obj *types.Order) (string, e func (r *myOrderResolver) Remaining(ctx context.Context, obj *types.Order) (string, error) { return strconv.FormatUint(obj.Remaining, 10), nil } + func (r *myOrderResolver) Status(ctx context.Context, obj *types.Order) (OrderStatus, error) { - return OrderStatus(obj.Status.String()), nil + return convertOrderStatusFromProto(obj.Status) } + func (r *myOrderResolver) CreatedAt(ctx context.Context, obj *types.Order) (string, error) { return vegatime.Format(vegatime.UnixNano(obj.CreatedAt)), nil } @@ -1240,6 +1201,10 @@ func (r *myTradeResolver) Seller(ctx context.Context, obj *types.Trade) (*types. return res.Party, nil } +func (r *myTradeResolver) Type(ctx context.Context, obj *proto.Trade) (TradeType, error) { + return convertTradeTypeFromProto(obj.Type) +} + // END: Trade Resolver // BEGIN: Candle Resolver @@ -1268,13 +1233,7 @@ func (r *myCandleResolver) Timestamp(ctx context.Context, obj *types.Candle) (st return strconv.FormatInt(obj.Timestamp, 10), nil } func (r *myCandleResolver) Interval(ctx context.Context, obj *types.Candle) (Interval, error) { - interval := Interval(obj.Interval.String()) - if interval.IsValid() { - return interval, nil - } - r.log.Warn("Interval conversion from proto to gql type failed, falling back to default: I15M", - logging.String("interval", interval.String())) - return IntervalI15m, nil + return convertIntervalFromProto(obj.Interval) } // END: Candle Resolver @@ -1443,13 +1402,13 @@ func (r *myMutationResolver) PrepareOrderSubmit(ctx context.Context, market, par } order.PartyID = party - if order.TimeInForce, err = parseOrderTimeInForce(timeInForce); err != nil { + if order.TimeInForce, err = convertOrderTimeInForceToProto(timeInForce); err != nil { return nil, err } - if order.Side, err = parseSide(&side); err != nil { + if order.Side, err = convertSideToProto(side); err != nil { return nil, err } - if order.Type, err = parseOrderType(ty); err != nil { + if order.Type, err = convertOrderTypeToProto(ty); err != nil { return nil, err } @@ -1518,11 +1477,6 @@ func (r *myMutationResolver) PrepareOrderCancel(ctx context.Context, id string, func (r *myMutationResolver) PrepareProposal( ctx context.Context, partyID string, reference *string, proposalTerms ProposalTermsInput) (*PreparedProposal, error) { - - if proposalTerms.MinParticipationStake < 0 { - return nil, errors.New("minParticipationStake is invalid, must be positive") - } - var ref string if reference != nil { ref = *reference @@ -1552,26 +1506,31 @@ func (r *myMutationResolver) PrepareVote(ctx context.Context, value VoteValue, p if err != nil { return nil, err } + protoValue, err := convertVoteValueToProto(value) + if err != nil { + return nil, err + } req := &protoapi.PrepareVoteRequest{ Vote: &types.Vote{ - Value: types.Vote_VALUE_NO, + Value: protoValue, PartyID: partyID, ProposalID: proposalID, }, } - if value == VoteValueYes { - req.Vote.Value = types.Vote_VALUE_YES - } resp, err := r.tradingClient.PrepareVote(ctx, req) if err != nil { return nil, err } + gqlValue, err := convertVoteValueFromProto(resp.Vote.Value) + if err != nil { + return nil, err + } return &PreparedVote{ Blob: base64.StdEncoding.EncodeToString(resp.Blob), Vote: &ProposalVote{ Vote: &Vote{ Party: party, - Value: VoteValueFromProto(resp.Vote.Value), + Value: gqlValue, }, ProposalID: resp.Vote.ProposalID, }, @@ -1607,7 +1566,7 @@ func (r *myMutationResolver) PrepareOrderAmend(ctx context.Context, id string, p return nil, errors.New("invalid size, could not convert to unsigned int") } - order.TimeInForce, err = parseOrderTimeInForce(tif) + order.TimeInForce, err = convertOrderTimeInForceToProto(tif) if err != nil { r.log.Error("unable to parse time in force in order amend", logging.Error(err)) @@ -1919,7 +1878,7 @@ func (r *mySubscriptionResolver) MarketDepth(ctx context.Context, market string) func (r *mySubscriptionResolver) Candles(ctx context.Context, market string, interval Interval) (<-chan *types.Candle, error) { - pinterval, err := convertInterval(interval) + pinterval, err := convertIntervalToProto(interval) if err != nil { r.log.Debug("invalid interval for candles subscriptions", logging.Error(err)) } @@ -2109,18 +2068,7 @@ func (r *myAccountResolver) Market(ctx context.Context, acc *types.Account) (*Ma } func (r *myAccountResolver) Type(ctx context.Context, obj *types.Account) (AccountType, error) { - var t AccountType - switch obj.Type { - case types.AccountType_ACCOUNT_TYPE_MARGIN: - return AccountTypeMargin, nil - case types.AccountType_ACCOUNT_TYPE_GENERAL: - return AccountTypeGeneral, nil - case types.AccountType_ACCOUNT_TYPE_INSURANCE: - return AccountTypeInsurance, nil - case types.AccountType_ACCOUNT_TYPE_SETTLEMENT: - return AccountTypeSettlement, nil - } - return t, ErrUnknownAccountType + return convertAccountTypeFromProto(obj.Type) } // END: Account Resolver diff --git a/gateway/graphql/schema.graphql b/gateway/graphql/schema.graphql index 3178e96eb37..a46d2b84874 100644 --- a/gateway/graphql/schema.graphql +++ b/gateway/graphql/schema.graphql @@ -888,6 +888,22 @@ type Trade { "RFC3339Nano for when the trade occurred" createdAt: String! + + "The type of trade" + type: TradeType! +} + +"Valid trade types" +enum TradeType { + + "Default trade type" + Default + + "Network close-out - good" + NetworkCloseOutGood + + "Network close-out - bad" + NetworkCloseOutBad } "An account record" @@ -930,12 +946,12 @@ enum OrderStatus { """ Active - "The order is cancelled, the order could be partially filled or unfilled before it was cancelled. It is not possible to cancel an order with 0 remaining." - Cancelled - "This order trades any amount and as much as possible and remains on the book until it either trades completely or expires." Expired + "The order is cancelled, the order could be partially filled or unfilled before it was cancelled. It is not possible to cancel an order with 0 remaining." + Cancelled + "This order was of type IOC or FOK and could not be processed by the matching engine due to lack of liquidity." Stopped @@ -944,40 +960,70 @@ enum OrderStatus { "This order was rejected while beeing processed in the core." Rejected + + "This order was partially filled." + PartiallyFilled } "Reason for the order beeing rejected by the core node" enum RejectionReason { + "Market id is invalid" InvalidMarketId + "Order id is invalid" InvalidOrderId + "Order is out of sequence" OrderOutOfSequence + "Remaining size in the order is invalid" InvalidRemainingSize + "Time has failed us" TimeFailure + "Unable to remove the order" OrderRemovalFailure + "Expiration time is invalid" InvalidExpirationTime + "Order reference is invalid" InvalidOrderReference + "Edit is not allowed" EditNotAllowed + "Order amend fail" OrderAmendFailure + "Order does not exist" OrderNotFound + "Party id is invalid" InvalidPartyId + "Market is closed" MarketClosed + "Margin check failed" MarginCheckFailed + + "Order missing general account" + MissingGeneralAccount + "An internal error happend" InternalError + + "Invalid size" + InvalidSize + + "Invalid persistence" + InvalidPersistence + + "Invalid type" + InvalidType } enum OrderType { @@ -1210,10 +1256,27 @@ type UpdateNetwork { maxEnactInSeconds: Int """ - Network parameter that restricts the minimum participation stake - required for a proposal to pass. + Network parameter that sets participation level required for any proposal to pass. + Value from 0 to 1. + """ + requiredParticipation: Float + """ + Network parameter that sets majority level required for any proposal to pass. + Value from 0.5 to 1. + """ + requiredMajority: Float + + """ + Network parameter that sets minimum balance required for a party + to be able to submit a new proposal. Value greater than 0 to 1. + """ + minProposerBalance: Float + """ - minParticipationStake: Int + Network parameter that sets minimum balance required for a party + to be able to cast a vote. Value greater than 0 to 1. + """ + minVoterBalance: Float } "Allows submitting a proposal for changing governance network parameters" @@ -1242,10 +1305,27 @@ input UpdateNetworkInput { maxEnactInSeconds: Int """ - Network parameter that restricts the minimum participation stake - required for a proposal to pass. + Network parameter that sets participation level required for any proposal to pass. + Value from 0 to 1. + """ + requiredParticipation: Float """ - minParticipationStake: Int + Network parameter that sets majority level required for any proposal to pass. + Value from 0.5 to 1. + """ + requiredMajority: Float + + """ + Network parameter that sets minimum balance required for a party + to be able to submit a new proposal. Value greater than 0 to 1. + """ + minProposerBalance: Float + + """ + Network parameter that sets minimum balance required for a party + to be able to cast a vote. Value greater than 0 to 1. + """ + minVoterBalance: Float } @@ -1253,31 +1333,54 @@ union ProposalChange = UpdateMarket | NewMarket | UpdateNetwork # there are no unions for input types as of today, see: https://github.com/graphql/graphql-spec/issues/488 type ProposalTerms { - "ISO-8601 time and date when voting closes for this proposal." + """ + ISO-8601 time and date when voting closes for this proposal. + Constrained by "minCloseInSeconds" and "maxCloseInSeconds" network parameters. + """ closingDatetime: String! - "ISO-8601 time and date when this proposal is executed (if passed). Note that it has to be after closing date time." + """ + ISO-8601 time and date when this proposal is executed (if passed). Note that it has to be after closing date time. + Constrained by "minEnactInSeconds" and "maxEnactInSeconds" network parameters. + """ enactmentDatetime: String! - "Minimum participation stake required for this proposal to pass" - minParticipationStake: Int! - "Actual change being introduced by the proposal" - change: ProposalChange + + "Actual change being introduced by the proposal - action the proposal triggers if passed and enacted." + change: ProposalChange! } # there are no unions for input types as of today, see: https://github.com/graphql/graphql-spec/issues/488 "Proposal terms input. Only one kind of change is expected. Proposals with no changes or more than one will not be accepted." input ProposalTermsInput { - "ISO-8601 time and date when voting closes for this proposal." + """ + ISO-8601 time and date when voting closes for this proposal. + Constrained by "minCloseInSeconds" and "maxCloseInSeconds" network parameters. + """ closingDatetime: String! - "ISO-8601 time and date when this proposal is executed (if passed). Note that it has to be after closing date time." + """ + ISO-8601 time and date when this proposal is executed (if passed). Note that it has to be after closing date time. + Constrained by "minEnactInSeconds" and "maxEnactInSeconds" network parameters. + """ enactmentDatetime: String! - "Minimum participation stake required for this proposal to pass" - minParticipationStake: Int! - - "Optional field to define update market change. If this is set along with another change, proposal will not be accepted." - updateMarket: UpdateMarketInput - "Optional field to define new market change. If this is set along with another change, proposal will not be accepted." + + + """ + Field defining new market change - the proposal will create new market if passed and enacted. + It can only be set if "updateMarket" and "updateNetwork" are not set (the proposal will be rejected otherwise). + One of "newMarket", "updateMarket", "updateNetwork" must be set (the proposal will be rejected otherwise). + """ newMarket: NewMarketInput - "Optional field to define an update of network parameters. If this is set along with another change, proposal will not be accepted." + """ + Field defining update market change - the proposal will update existing market if passed and enacted. + It can only be set if "newMarket" and "updateNetwork" are not set (the proposal will be rejected otherwise). + One of "newMarket", "updateMarket", "updateNetwork" must be set (the proposal will be rejected otherwise). + """ + updateMarket: UpdateMarketInput + + """ + Field defining update network change - the proposal will update Vega network parameters if passed and enacted. + It can only be set if "newMarket" and "updateMarket" are not set (the proposal will be rejected otherwise). + One of "newMarket", "updateMarket", "updateNetwork" must be set (the proposal will be rejected otherwise). + """ updateNetwork: UpdateNetworkInput } diff --git a/go.mod b/go.mod index 3eda0648337..a8f2bbcbb97 100644 --- a/go.mod +++ b/go.mod @@ -1,12 +1,11 @@ module code.vegaprotocol.io/vega -go 1.13 +go 1.14 require ( code.vegaprotocol.io/quant v0.1.0 github.com/99designs/gqlgen v0.11.3 github.com/blang/semver v3.5.1+incompatible - github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32 // indirect github.com/cenkalti/backoff/v4 v4.0.0 github.com/cucumber/godog v0.8.1 github.com/dgraph-io/badger/v2 v2.0.3 @@ -14,35 +13,29 @@ require ( github.com/ethereum/go-ethereum v1.9.12 github.com/fsnotify/fsnotify v1.4.7 github.com/golang/mock v1.2.0 - github.com/golang/protobuf v1.3.2 + github.com/golang/protobuf v1.4.0 github.com/google/btree v1.0.0 github.com/google/protobuf v3.7.0+incompatible // indirect github.com/gorilla/handlers v1.4.0 // indirect - github.com/gorilla/websocket v1.4.1 - github.com/grpc-ecosystem/grpc-gateway v1.9.0 + github.com/gorilla/websocket v1.4.2 + github.com/grpc-ecosystem/grpc-gateway v1.9.5 github.com/julienschmidt/httprouter v1.2.0 github.com/mwitkow/go-proto-validators v0.2.0 - github.com/pkg/errors v0.8.1 - github.com/prometheus/client_golang v0.9.3 - github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a // indirect + github.com/pkg/errors v0.9.1 + github.com/prometheus/client_golang v1.5.1 github.com/rs/cors v1.7.0 github.com/satori/go.uuid v1.2.0 github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 - github.com/spf13/cobra v0.0.5 - github.com/spf13/viper v1.5.0 - github.com/stretchr/testify v1.4.0 - github.com/tendermint/tendermint v0.32.9 + github.com/spf13/cobra v1.0.0 + github.com/spf13/viper v1.6.3 + github.com/stretchr/testify v1.5.1 + github.com/tendermint/tendermint v0.33.5 github.com/vegaprotocol/modvendor v0.0.2 // indirect github.com/vektah/gqlparser v1.3.1 github.com/vektah/gqlparser/v2 v2.0.1 github.com/zannen/toml v0.3.2 go.elastic.co/apm/module/apmhttp v1.8.0 - go.uber.org/zap v1.10.0 + go.uber.org/zap v1.13.0 golang.org/x/crypto v0.0.0-20200414173820-0848c9571904 - google.golang.org/grpc v1.25.1 -) - -replace ( - github.com/golang/protobuf => github.com/golang/protobuf v1.3.2 - github.com/tendermint/tendermint => github.com/vegaprotocol/tendermint v0.32.109 + google.golang.org/grpc v1.28.1 ) diff --git a/go.sum b/go.sum index 68900ebb533..0b78cd2d66d 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,5 @@ 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= code.vegaprotocol.io/quant v0.1.0 h1:RlSM9R59ahQ1CgmYmiYkPYGopUrdxd3Ood22kaGWk5Q= code.vegaprotocol.io/quant v0.1.0/go.mod h1:fQm5KvyuSwQuFFrzIXyN83Vz6m9tKfx2UCMls/gn1bo= github.com/99designs/gqlgen v0.10.2 h1:FfjCqIWejHDJeLpQTI0neoZo5vDO3sdo5oNCucet3A0= @@ -21,12 +22,17 @@ github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbt github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= 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/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= +github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= 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/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.5 h1:zl/OfRA6nftbBK9qTohYBJ5xvw6C/oNKizR7cZGl3cI= github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= +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-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/VictoriaMetrics/fastcache v1.5.3 h1:2odJnXLbFZcoV9KYtQ+7TH1UOq3dn3AssMgieaezkR4= @@ -35,44 +41,67 @@ github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrd github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/Workiva/go-datastructures v1.0.50 h1:slDmfW6KCHcC7U+LP3DDBbm4fqTwZGn1beOFPfGaLvo= github.com/Workiva/go-datastructures v1.0.50/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= +github.com/Workiva/go-datastructures v1.0.52/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= 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/agnivade/levenshtein v1.0.1 h1:3oJU7J3FGFmyhn8KHjmVaZCN5hxTr7GxgRue+sxIXdQ= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/agnivade/levenshtein v1.0.3 h1:M5ZnqLOoZR8ygVq0FfkXsNOKzMCk0xRiow0R5+5VkQ0= github.com/agnivade/levenshtein v1.0.3/go.mod h1:4SFRZbbXWLF4MU1T9Qg0pGgH3Pjs+t6ie5efyrwRJXs= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU= 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 h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY= 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/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +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/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 h1:rtI0fD4oG/8eVokGVPYJEW1F88p1ZNgXiEIs9thEE4A= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= +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/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/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.25.48/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 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +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/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32 h1:qkOC5Gd33k54tobS36cXdAzJbeHaduLtnLQQwNoIi78= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= +github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803 h1:j3AgPKKZtZStM2nyhrDSLSYgT7YHrZKdSkq1OYeLjvM= github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v4 v4.0.0 h1:6VeaLF9aI+MAUQ95106HwWzYZgJJpZ4stumjj6RFYAU= github.com/cenkalti/backoff/v4 v4.0.0/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -83,18 +112,30 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf github.com/cespare/xxhash/v2 v2.0.1-0.20190104013014-3767db7a7e18/go.mod h1:HD5P3vAIAh+Y2GAxg0PrPN1P8WkepXGpjbUPDHJqqKM= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +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/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +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/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.13+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-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/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/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d h1:49RLWk1j44Xu4fjHb6JFYmeUnDORVwHNkDxaQ0ctCVU= +github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= 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 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= +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/cucumber/godog v0.8.1 h1:lVb+X41I4YDreE+ibZ50bdXmySxgRviYFgKY6Aw4XE8= github.com/cucumber/godog v0.8.1/go.mod h1:vSh3r/lM+psC1BPXvdkSEuNjmXfpVqrMGYAElF6hxnA= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -122,10 +163,16 @@ github.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c/go.mod h1:if7Fbed8 github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/dop251/goja v0.0.0-20200219165308-d1232e640a87/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= +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 v0.0.0-20160512033002-935e0e8a636c h1:JHHhtb9XWJrGNMcrVP6vyzO4dusgi/HnceHTgxSejUM= github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elastic/go-sysinfo v1.0.1 h1:lzGPX2sIXaETeMXitXL2XZU8K4B7k7JBhIKWxdOdUt8= github.com/elastic/go-sysinfo v1.0.1/go.mod h1:O/D5m1VpYLwGjCYzEt63g3Z1uO3jXfwyzzjiW90t8cY= github.com/elastic/go-sysinfo v1.1.1 h1:ZVlaLDyhVkDfjwPGU55CQRCRolNpc7P0BbyhhQZQmMI= @@ -134,7 +181,10 @@ github.com/elastic/go-windows v1.0.0 h1:qLURgZFkkrYyTTkvYpsZIgf83AUsdIHfvlJaqaZ7 github.com/elastic/go-windows v1.0.0/go.mod h1:TsU0Nrp7/y3+VwE82FoZF8gC/XFg/Elz6CcloAxnPgU= github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa h1:XKAhUk/dtp+CV0VO6mhG2V7jA9vbcGcnYF/Ay9NjZrY= github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs= +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.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/etcd-io/bbolt v1.3.3 h1:gSJmxrs37LgTqR/oyJBWok6k6SvXEUerFTbltIhXkBM= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= @@ -147,10 +197,13 @@ github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqL github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 h1:E2s37DuLxFhQDg5gKsWoLBOB0n+ZW8s599zru8FJ2/Y= github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc h1:jtW8jbpkO4YirRSyepBOH8E+2HEw6/hKkBvFPwhUN8c= github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +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 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= @@ -160,30 +213,51 @@ github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxm github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= +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 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 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 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 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-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/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 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +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-0.20190517061210-b285ee9cfc6c/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= 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.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 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +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 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -191,35 +265,76 @@ github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= 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/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/protobuf v3.7.0+incompatible/go.mod h1:lUQ9D1ePzbH2PrIS7ob/bjm9HXyH5WHB0Akwh7URreM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v1.4.0 h1:XulKRWSQK5uChr4pEgSE4Tc/OcmnU9GJuSwdog/tZsA= github.com/gorilla/handlers v1.4.0/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +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/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-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= 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/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= 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-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0 h1:bM6ZAFZmc/wPFaRDi0d5L7hGEZEx/2u+Tmr2evNHDiI= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5 h1:UImYN5qQ8tuGpGE16ZmjvcTtTw24zw1QAp/SlnNrZhI= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= +github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= +github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= +github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= +github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= +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.0.0-20160813221303-0a025b7e63ad/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= 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 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3 h1:DqD8eigqlUm0+znmx7zhL0xvTW3+e1jCekJMfBUADWI= github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3/go.mod h1:MZ2ZmwcBpvOoJ22IJsc7va19ZwoheaBk43rKg12SKag= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458 h1:6OvNmYgJyexcZ3pYbTI9jWx5tHo1Dee/tWbLMfPe2TA= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -231,6 +346,11 @@ github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8 github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +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.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= @@ -252,36 +372,67 @@ 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/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= +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/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +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/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.0 h1:v2XXALHHh6zHfYTJ+cSkwtyffnaOyR1MXaA91mTrb8o= github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +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.5-0.20180830101745-3fb116b82035 h1:USWjF42jDCSEeikX/G1g40ZWnsPXN5WkZ4jMHZWyBK4= github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/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.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-zglob v0.0.0-20180803001819-2ea3427bfa53/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= 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/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0= +github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= +github.com/minio/highwayhash v1.0.0/go.mod h1:xQboMTeM9nY9v/LlAOxFctujiv5+Aq2hR5dxBpaMbdc= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +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 v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +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-proto-validators v0.2.0 h1:F6LFfmgVnfULfaRsQWBbe7F7ocuHCr9+7m+GAeDzNbQ= github.com/mwitkow/go-proto-validators v0.2.0/go.mod h1:ZfA1hW+UH/2ZHOWvQ3HnQaU0DtnpXu850MZiy+YUgcc= github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= +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/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/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +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-0.20190409134802-7e037d187b0c h1:1RHs3tNxjXGHeul8z2t6H2N2TlAqpKe5yryJztRx4Jk= github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= @@ -290,43 +441,81 @@ github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +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/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 v0.0.0-20170112150404-1b00554d8222 h1:goeTyGkArOZIVOMA0dQbyuPWGNQJZGPwPu/QS9GlpnA= github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= +github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= 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/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= +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 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= 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 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/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 v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.5.1 h1:bdHYieyGlH+6OLEk2YQha8THib30KP0/yD0YH9m6xcA= +github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= 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 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM= 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 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= 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.0-20190425082905-87a4384529e0/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3 h1:CTwfnzjQ+8dS6MhHHu4YswVAD99sL2wjPqP+VkURmKE= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= +github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= 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 v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= @@ -336,10 +525,13 @@ github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNue github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= 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/santhosh-tekuri/jsonschema v1.2.4 h1:hNhW8e7t+H1vgY+1QeEQpveR6D4+OwKPXCfD2aieJis= github.com/santhosh-tekuri/jsonschema v1.2.4/go.mod h1:TEAUOeZSmIxTTuHatJzrvARHiuO9LYd+cIxzgEHCQI4= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= @@ -351,8 +543,12 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo= 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/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/snikch/goodman v0.0.0-20171125024755-10e37e294daa/go.mod h1:oJyF+mSPHbB5mVY2iO9KV3pTt/QbIkGaO8gQ2WrDbP4= 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.0.1-0.20190317074736-539464a789e9/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= @@ -362,21 +558,31 @@ github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= 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 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.5.0 h1:GpsTwfsQ27oS/Aha/6d1oD7tpKIqWnOA6tgOX9HHkt4= github.com/spf13/viper v1.5.0/go.mod h1:AkYRkVJF8TkSG/xet6PzXX+l39KhhXa2pdqVSxnTcn4= +github.com/spf13/viper v1.6.3 h1:pDDu1OyEDTKzpJwdq4TiuLyMsUgRa/BT5cn5O62NoHs= +github.com/spf13/viper v1.6.3/go.mod h1:jUMtyi0/lB5yZH/FjyGAoH7IMNrIhlBf6pXZmbMDvzw= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM= github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= +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 v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -384,6 +590,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stumble/gorocksdb v0.0.3 h1:9UU+QA1pqFYJuf9+5p7z1IqdE5k0mma4UAeu2wmX8kA= github.com/stumble/gorocksdb v0.0.3/go.mod h1:v6IHdFBXk5DJ1K4FZ0xi+eY737quiiBxYtSWXadLybY= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= @@ -392,12 +600,17 @@ github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965 h1:1oFLiOyVl+W7 github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d h1:gZZadD8H+fF+n9CmNhYL1Y0dJB+kLOmKd7FbPJLeGHs= github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= +github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= github.com/tendermint/go-amino v0.14.1 h1:o2WudxNfdLNBwMyl2dqOJxiro5rfrEaU0Ugs6offJMk= github.com/tendermint/go-amino v0.14.1/go.mod h1:i/UKE5Uocn+argJJBb12qTZsCDBcAYMbR92AaJVmKso= github.com/tendermint/tendermint v0.32.9 h1:++dR46xpBq/yfQx2c5KyrZmb15p2jw9Q5iEtTB82d8s= github.com/tendermint/tendermint v0.32.9/go.mod h1:5/B1XZjNYtVBso8o1l/Eg4A0Mhu42lDcmftoQl95j/E= +github.com/tendermint/tendermint v0.33.5 h1:jYgRd9ImkzA9iOyhpmgreYsqSB6tpDa6/rXYPb8HKE8= +github.com/tendermint/tendermint v0.33.5/go.mod h1:0yUs9eIuuDq07nQql9BmI30FtYGcEC60Tu5JzB5IezM= github.com/tendermint/tm-db v0.2.0 h1:rJxgdqn6fIiVJZy4zLpY1qVlyD0TU6vhkT4kEf71TQQ= github.com/tendermint/tm-db v0.2.0/go.mod h1:0cPKWu2Mou3IlxecH+MEUSYc1Ch537alLe6CpFrKzgw= +github.com/tendermint/tm-db v0.5.1/go.mod h1:g92zWjHpCYlEvQXvy9M168Su8V1IBEeawpXVVBaK4f4= +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/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= @@ -440,20 +653,39 @@ go.elastic.co/fastjson v1.0.0/go.mod h1:PmeUOMMtLHQr9ZS9J9owrAVg0FkaZDRZJEFTTGHt go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +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.22.2/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 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU= +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-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 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/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-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-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-20200311171314-f7b00557c8c4 h1:QmwruyY+bKbDDL0BaglrbZABEali68eoMFhTZpCjYVA= golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200406173513-056763e48d71/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200414173820-0848c9571904 h1:bXoxMPcSLOq08zI3/c5dEBT6lE4eh+jOh886GHrn6V8= golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -463,55 +695,85 @@ golang.org/x/exp v0.0.0-20190429183610-475c5042d3f1/go.mod h1:ZjyILWgesfNpC6sMxT golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 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-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/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-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +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-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk= 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-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0= 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 h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 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/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-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/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-20190130150945-aca44879d564/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-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190425145619-16072639606e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/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 h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ= 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-20191025021431-6c3a3bfe00ae/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-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= 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/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= @@ -520,11 +782,19 @@ golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGm 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-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 h1:5Beo0mZN8dRzgrMMkDp0jc8YXQKx9DiJ2k1dkvGsn5A= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +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-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589 h1:rjUrONFu4kLchcZTfp3/96bR8bW8dIa8uz3cR5n0cgM= golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +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 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -532,26 +802,51 @@ gonum.org/v1/gonum v0.0.0-20190424212039-2a1643c79af2 h1:KTRD63fFTJiXuYJfxAI7BLu gonum.org/v1/gonum v0.0.0-20190424212039-2a1643c79af2/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0 h1:OE9mWmgKkjJyEmDAAtGMPjXu+YNeGvK9VTSHY6+Qihc= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= 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/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/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-20190425155659-357c62f0e4bb/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-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +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.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.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +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.25.1 h1:wdKvqQk7IttEw92GoRyKG2IDrUIpgpj6H6m81yfeMW0= 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.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.28.1 h1:C1QC6KzgSiLyBabDi87BbjaGreoRgGUF5nOyvfrAZ1k= +google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +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 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= 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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= 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/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190213234257-ec84240a7772 h1:hhsSf/5z74Ck/DJYc+R8zpq8KGm7uJvpdLRQED/IedA= @@ -561,16 +856,24 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= +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 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +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-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= howett.net/plist v0.0.0-20181124034731-591f970eefbb h1:jhnBjNi9UFpfpl8YZhA9CrOqpnJdvzuiHsl/dnxl11M= howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k= diff --git a/governance/engine.go b/governance/engine.go index 327976ccef4..88b61b4a3c1 100644 --- a/governance/engine.go +++ b/governance/engine.go @@ -11,18 +11,21 @@ import ( ) var ( - ErrProposalNotFound = errors.New("proposal not found") - ErrProposalIsDuplicate = errors.New("proposal with given ID already exists") - // Validation errors - - ErrProposalCloseTimeTooSoon = errors.New("proposal closes too soon") - ErrProposalCloseTimeTooLate = errors.New("proposal closes too late") - ErrProposalEnactTimeTooSoon = errors.New("proposal enactment times too soon") - ErrProposalEnactTimeTooLate = errors.New("proposal enactment times too late") - ErrProposalInsufficientTokens = errors.New("proposal requires more tokens than party has") - - ErrVoterInsufficientTokens = errors.New("vote requires more tokens than party has") - ErrVotePeriodExpired = errors.New("proposal voting has been closed") + ErrProposalInvalidState = errors.New("proposal state not valid, only open can be submitted") + ErrProposalNotFound = errors.New("found no open proposal with the id") + ErrProposalIsDuplicate = errors.New("proposal with given ID already exists") + ErrProposalCloseTimeTooSoon = errors.New("proposal closes too soon") + ErrProposalCloseTimeTooLate = errors.New("proposal closes too late") + ErrProposalEnactTimeTooSoon = errors.New("proposal enactment time is too soon") + ErrProposalEnactTimeTooLate = errors.New("proposal enactment time is too late") + ErrProposalInsufficientTokens = errors.New("party requires more tokens to submit a proposal") + ErrProposalMinPaticipationStakeTooLow = errors.New("proposal minimum participation stake is too low") + ErrProposalMinPaticipationStakeInvalid = errors.New("proposal minimum participation stake is out of bounds [0..1]") + ErrProposalMinRequiredMajorityStakeTooLow = errors.New("proposal minimum required majority stake is too low") + ErrProposalMinRequiredMajorityStakeInvalid = errors.New("proposal minimum required majority stake is out of bounds [0.5..1]") + ErrVoterInsufficientTokens = errors.New("vote requires more tokens than party has") + ErrProposalPassed = errors.New("proposal has passed and can no longer be voted on") + ErrNoNetworkParams = errors.New("network parameters were not configured for this proposal type") ) // Accounts ... @@ -44,43 +47,38 @@ type VoteBuf interface { Add(types.Vote) } +// Engine is the governance engine that handles proposal and vote lifecycle. type Engine struct { Config - accs Accounts - buf Buffer - vbuf VoteBuf - log *logging.Logger - mu sync.Mutex - currentTime time.Time - proposals map[string]*governanceData - proposalRefs map[string]*governanceData - networkParams NetworkParameters + mu sync.Mutex + log *logging.Logger + + accounts Accounts + buf Buffer + vbuf VoteBuf + currentTime time.Time + + activeProposals map[string]*proposalData + networkParams NetworkParameters } -type governanceData struct { +type proposalData struct { *types.Proposal yes map[string]*types.Vote no map[string]*types.Vote } +// NewEngine creates new governance engine instance func NewEngine(log *logging.Logger, cfg Config, params *NetworkParameters, accs Accounts, buf Buffer, vbuf VoteBuf, now time.Time) *Engine { - log.Debug("Governance parameters", - logging.String("MinClose", params.minClose.String()), - logging.String("MaxClose", params.maxClose.String()), - logging.String("MinEnact", params.minEnact.String()), - logging.String("MaxEnact", params.maxEnact.String()), - logging.Uint64("MinParticipationStake", params.minParticipationStake), - ) return &Engine{ - Config: cfg, - accs: accs, - buf: buf, - vbuf: vbuf, - log: log, - currentTime: now, - proposals: map[string]*governanceData{}, - proposalRefs: map[string]*governanceData{}, - networkParams: *params, + Config: cfg, + accounts: accs, + buf: buf, + vbuf: vbuf, + log: log, + currentTime: now, + activeProposals: map[string]*proposalData{}, + networkParams: *params, } } @@ -100,131 +98,173 @@ func (e *Engine) ReloadConf(cfg Config) { e.mu.Unlock() } -// OnChainTimeUpdate - update curtime, expire proposals +// OnChainTimeUpdate triggers time bound state changes. func (e *Engine) OnChainTimeUpdate(t time.Time) []*types.Proposal { e.currentTime = t - now := t.Unix() + var toBeEnacted []*types.Proposal + if len(e.activeProposals) > 0 { + now := t.Unix() - totalStake := e.accs.GetTotalTokens() - counter := newStakeCounter(e.log, e.accs) + totalStake := e.accounts.GetTotalTokens() + counter := newStakeCounter(e.log, e.accounts) - var toBeEnacted []*types.Proposal - for k, p := range e.proposals { - if p.Terms.ClosingTimestamp < now { - e.closeProposal(p, counter, totalStake) - } - if p.State == types.Proposal_STATE_PASSED && p.Terms.EnactmentTimestamp < now { - toBeEnacted = append(toBeEnacted, p.Proposal) - delete(e.proposals, k) - delete(e.proposalRefs, p.Reference) + for id, proposal := range e.activeProposals { + if proposal.Terms.ClosingTimestamp < now { + e.closeProposal(proposal, counter, totalStake) + } + + if proposal.State != types.Proposal_STATE_OPEN && proposal.State != types.Proposal_STATE_PASSED { + delete(e.activeProposals, id) + } else if proposal.State == types.Proposal_STATE_PASSED && proposal.Terms.EnactmentTimestamp < now { + toBeEnacted = append(toBeEnacted, proposal.Proposal) + delete(e.activeProposals, id) + } } } return toBeEnacted } -func (e *Engine) AddProposal(p types.Proposal) error { - // @TODO -> we probably should keep proposals in memory here - if cp, ok := e.proposals[p.ID]; ok && cp.State == p.State { - return ErrProposalIsDuplicate - } - if _, ok := e.proposalRefs[p.Reference]; ok { - return ErrProposalIsDuplicate - } - var err error - if err = e.validateProposal(p); err != nil { - p.State = types.Proposal_STATE_REJECTED +// SubmitProposal submits new proposal to the governance engine so it can be voted on, passed and enacted. +// Only open can be submitted and validated at this point. No further validation happens. +func (e *Engine) SubmitProposal(proposal types.Proposal) error { + if _, exists := e.activeProposals[proposal.ID]; exists { + return ErrProposalIsDuplicate // state is not allowed to change externally } - if p.State != types.Proposal_STATE_OPEN { - delete(e.proposals, p.ID) - delete(e.proposalRefs, p.Reference) - } else { - pv := governanceData{ - Proposal: &p, - yes: map[string]*types.Vote{}, - no: map[string]*types.Vote{}, + // Proposals ought to be read from the chain only once: when the proposal submission transaction is processed. + // After that they should be read from the core’s internal state (which can only be updated deterministically by transactions on the chain... + if proposal.State == types.Proposal_STATE_OPEN { + err := e.validateOpenProposal(proposal) + if err != nil { + proposal.State = types.Proposal_STATE_REJECTED + } else { + e.activeProposals[proposal.ID] = &proposalData{ + Proposal: &proposal, + yes: map[string]*types.Vote{}, + no: map[string]*types.Vote{}, + } } - e.proposals[p.ID] = &pv - e.proposalRefs[p.Reference] = &pv + e.buf.Add(proposal) + return err } - e.buf.Add(p) - return err + return ErrProposalInvalidState } -func (e *Engine) validateProposal(p types.Proposal) error { - tok, err := e.accs.GetPartyTokenAccount(p.PartyID) +func (e *Engine) getProposalParams(terms *types.ProposalTerms) (*ProposalParameters, error) { + if terms.GetNewMarket() != nil { + return &e.networkParams.newMarkets, nil + } + return nil, ErrNoNetworkParams +} + +// validates proposals read from the chain +func (e *Engine) validateOpenProposal(proposal types.Proposal) error { + params, err := e.getProposalParams(proposal.Terms) if err != nil { return err } - if tok.Balance < 1 { - return ErrProposalInsufficientTokens - } - if p.Terms.ClosingTimestamp < e.currentTime.Add(e.networkParams.minClose).Unix() { + if proposal.Terms.ClosingTimestamp < e.currentTime.Add(params.MinClose).Unix() { return ErrProposalCloseTimeTooSoon } - if p.Terms.ClosingTimestamp > e.currentTime.Add(e.networkParams.maxClose).Unix() { + if proposal.Terms.ClosingTimestamp > e.currentTime.Add(params.MaxClose).Unix() { return ErrProposalCloseTimeTooLate } - if p.Terms.EnactmentTimestamp < e.currentTime.Add(e.networkParams.minEnact).Unix() { + if proposal.Terms.EnactmentTimestamp < e.currentTime.Add(params.MinEnact).Unix() { return ErrProposalEnactTimeTooSoon } - if p.Terms.EnactmentTimestamp > e.currentTime.Add(e.networkParams.maxEnact).Unix() { + if proposal.Terms.EnactmentTimestamp > e.currentTime.Add(params.MaxEnact).Unix() { return ErrProposalEnactTimeTooLate } - + proposerTokens, err := getGovernanceTokens(e.accounts, proposal.PartyID) + if err != nil { + return err + } + totalTokens := e.accounts.GetTotalTokens() + if float32(proposerTokens) < float32(totalTokens)*params.MinProposerBalance { + return ErrProposalInsufficientTokens + } return nil } -func (e *Engine) AddVote(v types.Vote) error { - p, err := e.validateVote(v) +// AddVote adds vote onto an existing active proposal (if found) so the proposal could pass and be enacted +func (e *Engine) AddVote(vote types.Vote) error { + proposal, err := e.validateVote(vote) if err != nil { return err } // we only want to count the last vote, so add to yes/no map, delete from the other // if the party hasn't cast a vote yet, the delete is just a noop - if v.Value == types.Vote_VALUE_YES { - delete(p.no, v.PartyID) - p.yes[v.PartyID] = &v + if vote.Value == types.Vote_VALUE_YES { + delete(proposal.no, vote.PartyID) + proposal.yes[vote.PartyID] = &vote } else { - delete(p.yes, v.PartyID) - p.no[v.PartyID] = &v + delete(proposal.yes, vote.PartyID) + proposal.no[vote.PartyID] = &vote } - e.vbuf.Add(v) + e.vbuf.Add(vote) return nil } -func (e *Engine) validateVote(v types.Vote) (*governanceData, error) { - tacc, err := e.accs.GetPartyTokenAccount(v.PartyID) +func (e *Engine) validateVote(vote types.Vote) (*proposalData, error) { + proposal, found := e.activeProposals[vote.ProposalID] + if !found { + return nil, ErrProposalNotFound + } else if proposal.State == types.Proposal_STATE_PASSED { + return nil, ErrProposalPassed + } + + params, err := e.getProposalParams(proposal.Terms) if err != nil { return nil, err } - if tacc.Balance == 0 { - return nil, ErrVoterInsufficientTokens - } - p, ok := e.proposals[v.ProposalID] - if !ok { - return nil, ErrProposalNotFound + + voterTokens, err := getGovernanceTokens(e.accounts, vote.PartyID) + if err != nil { + return nil, err } - if p.Terms.ClosingTimestamp < e.currentTime.Unix() { - return nil, ErrVotePeriodExpired + totalTokens := e.accounts.GetTotalTokens() + if float32(voterTokens) < float32(totalTokens)*params.MinVoterBalance { + return nil, ErrVoterInsufficientTokens } - return p, nil + + return proposal, nil } -func (e *Engine) closeProposal(data *governanceData, counter *stakeCounter, totalStake uint64) { - proposal := data.Proposal +// sets proposal in either declined or passed state +func (e *Engine) closeProposal(proposal *proposalData, counter *stakeCounter, totalStake uint64) error { + if proposal.State == types.Proposal_STATE_OPEN { + proposal.State = types.Proposal_STATE_DECLINED // declined unless passed - yes := counter.countVotes(data.yes) - no := counter.countVotes(data.no) + params, err := e.getProposalParams(proposal.Terms) + if err != nil { + return err + } - proposal.State = types.Proposal_STATE_DECLINED - if yes > no { - participationStake := float64(yes + no) - minParticipationStake := float64(proposal.Terms.MinParticipationStake*totalStake) / 100 - if participationStake >= minParticipationStake { + yes := counter.countVotes(proposal.yes) + no := counter.countVotes(proposal.no) + totalVotes := float32(yes + no) + + // yes > (yes + no)* required majority ratio + if float32(yes) > totalVotes*params.RequiredMajority && + //(yes+no) >= (yes + no + novote)* required participation ratio + totalVotes >= float32(totalStake)*params.RequiredParticipation { proposal.State = types.Proposal_STATE_PASSED + e.log.Debug("Proposal passed", logging.String("proposal-id", proposal.ID)) + } else if totalVotes == 0 { + e.log.Info("Proposal declined - no votes", logging.String("proposal-id", proposal.ID)) + } else { + e.log.Info( + "Proposal declined", + logging.String("proposal-id", proposal.ID), + logging.Uint64("yes-votes", yes), + logging.Float32("min-yes-required", totalVotes*params.RequiredMajority), + logging.Float32("total-votes", totalVotes), + logging.Float32("min-total-votes-required", float32(totalStake)*params.RequiredParticipation), + logging.Float32("tokens", float32(totalStake)), + ) } + e.buf.Add(*proposal.Proposal) } - e.buf.Add(*proposal) + return nil } // stakeCounter caches token balance per party and counts votes @@ -254,16 +294,24 @@ func (s *stakeCounter) getTokens(partyID string) uint64 { if balance, found := s.balances[partyID]; found { return balance } - account, err := s.accounts.GetPartyTokenAccount(partyID) + balance, err := getGovernanceTokens(s.accounts, partyID) if err != nil { s.log.Error( - "Failed to get account for party", + "Failed to get governance tokens balance for party", logging.String("party-id", partyID), logging.Error(err), ) // not much we can do with the error as there is nowhere to buble up the error on tick return 0 } - s.balances[partyID] = account.Balance - return account.Balance + s.balances[partyID] = balance + return balance +} + +func getGovernanceTokens(accounts Accounts, partyID string) (uint64, error) { + account, err := accounts.GetPartyTokenAccount(partyID) + if err != nil { + return 0, err + } + return account.Balance, nil } diff --git a/governance/engine_test.go b/governance/engine_test.go index f4959d406d6..2c2cf4c96f9 100644 --- a/governance/engine_test.go +++ b/governance/engine_test.go @@ -1,6 +1,7 @@ package governance_test import ( + "fmt" "testing" "time" @@ -17,232 +18,645 @@ import ( type tstEngine struct { *governance.Engine - ctrl *gomock.Controller - accs *mocks.MockAccounts - buf *mocks.MockBuffer - vbuf *mocks.MockVoteBuf + ctrl *gomock.Controller + accs *mocks.MockAccounts + buf *mocks.MockBuffer + vbuf *mocks.MockVoteBuf + proposalCounter uint // to streamline proposal generation } -func TestProposals(t *testing.T) { - t.Run("Submit a valid proposal - success", testSubmitValidProposalSuccess) - t.Run("Submit a valid proposal - duplicate", testSubmitValidProposalDuplicate) - t.Run("Submit invalid proposal", testSubmitInvalidProposal) +func TestSubmitProposals(t *testing.T) { + t.Run("Submit a valid proposal - success", testSubmitValidProposal) + t.Run("Validate proposal state on submission", testProposalState) + t.Run("Validate duplicate proposal", testProposalDuplicate) + t.Run("Validate closing time", testClosingTime) + t.Run("Validate enactment time", testEnactmentTime) + t.Run("Validate proposer stake", testProposerStake) } -func TestVotes(t *testing.T) { - t.Run("Submit a valid vote - success", testSubmitValidVoteSuccess) +func testSubmitValidProposal(t *testing.T) { + eng := getTestEngine(t) + defer eng.ctrl.Finish() + + var balance uint64 = 123456789 + party := eng.makeValidParty("a-valid-party", balance) + + // to check min required level + eng.accs.EXPECT().GetTotalTokens().Times(1).Return(balance) + // once proposal is validated, it is added to the buffer + eng.buf.EXPECT().Add(gomock.Any()).Times(1).Do(func(p types.Proposal) { + assert.Equal(t, types.Proposal_STATE_OPEN, p.State) + assert.Equal(t, party.Id, p.PartyID) + }) + err := eng.SubmitProposal(eng.newOpenProposal(party.Id, time.Now())) + assert.NoError(t, err) } -func TestTimeUpdate(t *testing.T) { - t.Run("Accepted proposal on time update", testProposalAccepted) +func testProposalState(t *testing.T) { + eng := getTestEngine(t) + defer eng.ctrl.Finish() + + var tokens uint64 = 1000 + party := eng.makeValidParty("valid-party", tokens) + + unspecified := eng.newOpenProposal(party.Id, time.Now()) + unspecified.State = types.Proposal_STATE_UNSPECIFIED + err := eng.SubmitProposal(unspecified) + assert.Error(t, err) + assert.EqualError(t, governance.ErrProposalInvalidState, err.Error()) + + failed := eng.newOpenProposal(party.Id, time.Now()) + failed.State = types.Proposal_STATE_FAILED + err = eng.SubmitProposal(failed) + assert.Error(t, err) + assert.EqualError(t, governance.ErrProposalInvalidState, err.Error()) + + passed := eng.newOpenProposal(party.Id, time.Now()) + passed.State = types.Proposal_STATE_PASSED + err = eng.SubmitProposal(passed) + assert.Error(t, err) + assert.EqualError(t, governance.ErrProposalInvalidState, err.Error()) + + rejected := eng.newOpenProposal(party.Id, time.Now()) + rejected.State = types.Proposal_STATE_REJECTED + err = eng.SubmitProposal(rejected) + assert.Error(t, err) + assert.EqualError(t, governance.ErrProposalInvalidState, err.Error()) + + declined := eng.newOpenProposal(party.Id, time.Now()) + declined.State = types.Proposal_STATE_DECLINED + err = eng.SubmitProposal(declined) + assert.Error(t, err) + assert.EqualError(t, governance.ErrProposalInvalidState, err.Error()) + + enacted := eng.newOpenProposal(party.Id, time.Now()) + enacted.State = types.Proposal_STATE_ENACTED + err = eng.SubmitProposal(enacted) + assert.Error(t, err) + assert.EqualError(t, governance.ErrProposalInvalidState, err.Error()) + + eng.accs.EXPECT().GetTotalTokens().Times(1).Return(tokens) + eng.buf.EXPECT().Add(gomock.Any()).Times(1).Do(func(p types.Proposal) { + assert.Equal(t, types.Proposal_STATE_OPEN, p.State) + assert.Equal(t, party.Id, p.PartyID) + }) + err = eng.SubmitProposal(eng.newOpenProposal(party.Id, time.Now())) + assert.NoError(t, err) } -func testSubmitValidProposalSuccess(t *testing.T) { +func testProposalDuplicate(t *testing.T) { eng := getTestEngine(t) + defer eng.ctrl.Finish() + + var balance uint64 = 1000 + party := eng.makeValidParty("valid-party", balance) + eng.accs.EXPECT().GetTotalTokens().Times(1).Return(balance) + + eng.buf.EXPECT().Add(gomock.Any()).Times(1).Do(func(p types.Proposal) { + assert.Equal(t, types.Proposal_STATE_OPEN, p.State) + assert.Equal(t, party.Id, p.PartyID) + }) + + original := eng.newOpenProposal(party.Id, time.Now()) + err := eng.SubmitProposal(original) + assert.NoError(t, err) + + aCopy := original + aCopy.Reference = "this-is-a-copy" + err = eng.SubmitProposal(aCopy) + assert.Error(t, err) + assert.EqualError(t, governance.ErrProposalIsDuplicate, err.Error()) + aCopy = original + aCopy.State = types.Proposal_STATE_PASSED + err = eng.SubmitProposal(aCopy) + assert.Error(t, err) + assert.EqualError(t, governance.ErrProposalIsDuplicate, err.Error(), "reject atempt to change state indirectly") +} + +func testProposerStake(t *testing.T) { + eng := getTestEngine(t) defer eng.ctrl.Finish() - partyID := "party1" - now := time.Now() - acc := types.Account{ - Id: "acc-1", - Owner: partyID, - Balance: 1000, - Asset: collateral.TokenAsset, - } - prop := types.Proposal{ - ID: "prop-1", - Reference: "test-prop-1", - PartyID: partyID, - State: types.Proposal_STATE_OPEN, - Terms: &types.ProposalTerms{ - ClosingTimestamp: now.Add(48 * time.Hour).Unix(), - EnactmentTimestamp: now.Add(48 * time.Hour).Unix(), - MinParticipationStake: 55, - }, - } - eng.accs.EXPECT().GetPartyTokenAccount(partyID).Times(1).Return(&acc, nil) - eng.buf.EXPECT().Add(gomock.Any()).Times(1) - err := eng.AddProposal(prop) + + noAccountPartyID := "party" + + notFoundError := errors.New("account not found") + eng.accs.EXPECT().GetPartyTokenAccount(noAccountPartyID).Times(1).Return(nil, notFoundError) + + eng.buf.EXPECT().Add(gomock.Any()).Times(1).Do(func(p types.Proposal) { + assert.Equal(t, types.Proposal_STATE_REJECTED, p.State) + assert.Equal(t, noAccountPartyID, p.PartyID) + }) + err := eng.SubmitProposal(eng.newOpenProposal(noAccountPartyID, time.Now())) + assert.Error(t, err) + assert.EqualError(t, err, notFoundError.Error()) + + emptyParty := eng.makeValidParty("no-token-party", 0) + eng.accs.EXPECT().GetTotalTokens().Times(1).Return(uint64(123456)) + eng.buf.EXPECT().Add(gomock.Any()).Times(1).Do(func(p types.Proposal) { + assert.Equal(t, types.Proposal_STATE_REJECTED, p.State) + assert.Equal(t, emptyParty.Id, p.PartyID) + }) + err = eng.SubmitProposal(eng.newOpenProposal(emptyParty.Id, time.Now())) + assert.Error(t, err) + assert.EqualError(t, err, governance.ErrProposalInsufficientTokens.Error()) + + eng.accs.EXPECT().GetTotalTokens().Times(1).Return(uint64(123456)) + poshParty := eng.makeValidParty("party-with-tokens", 123456-100) + + eng.buf.EXPECT().Add(gomock.Any()).Times(1).Do(func(p types.Proposal) { + assert.Equal(t, types.Proposal_STATE_OPEN, p.State) + assert.Equal(t, poshParty.Id, p.PartyID) + }) + err = eng.SubmitProposal(eng.newOpenProposal(poshParty.Id, time.Now())) assert.NoError(t, err) } -func testSubmitValidProposalDuplicate(t *testing.T) { +func testClosingTime(t *testing.T) { eng := getTestEngine(t) defer eng.ctrl.Finish() - partyID := "party1" + + party := eng.makeValidParty("a-valid-party", 1) + + eng.buf.EXPECT().Add(gomock.Any()).Times(2).Do(func(p types.Proposal) { + assert.Equal(t, types.Proposal_STATE_REJECTED, p.State) + assert.Equal(t, party.Id, p.PartyID) + }) + now := time.Now() - acc := types.Account{ - Id: "acc-1", - Owner: partyID, - Balance: 1000, - Asset: collateral.TokenAsset, - } - prop := types.Proposal{ - ID: "prop-1", - Reference: "test-prop-1", - PartyID: partyID, - State: types.Proposal_STATE_OPEN, - Terms: &types.ProposalTerms{ - ClosingTimestamp: now.Add(100 * time.Hour).Unix(), - EnactmentTimestamp: now.Add(240 * time.Hour).Unix(), - MinParticipationStake: 55, - }, - } - eng.accs.EXPECT().GetPartyTokenAccount(partyID).Times(1).Return(&acc, nil) + tooEarly := eng.newOpenProposal(party.Id, now) + tooEarly.Terms.ClosingTimestamp = now.Unix() + err := eng.SubmitProposal(tooEarly) + assert.Error(t, err) + assert.EqualError(t, err, governance.ErrProposalCloseTimeTooSoon.Error()) + + tooLate := eng.newOpenProposal(party.Id, now) + tooLate.Terms.ClosingTimestamp = now.Add(3 * 365 * 24 * time.Hour).Unix() + err = eng.SubmitProposal(tooLate) + assert.Error(t, err) + assert.EqualError(t, err, governance.ErrProposalCloseTimeTooLate.Error()) + + eng.accs.EXPECT().GetTotalTokens().Times(1).Return(uint64(1)) eng.buf.EXPECT().Add(gomock.Any()).Times(1).Do(func(p types.Proposal) { assert.Equal(t, types.Proposal_STATE_OPEN, p.State) + assert.Equal(t, party.Id, p.PartyID) }) - err := eng.AddProposal(prop) + err = eng.SubmitProposal(eng.newOpenProposal(party.Id, now)) assert.NoError(t, err) - did, dref := prop, prop - did.Reference = "Something else" - dref.ID = "foobar" - data := map[string]types.Proposal{ - "Duplicate ID": did, - "Duplicate Reference": dref, - } - for k, prop := range data { - err = eng.AddProposal(prop) - assert.Error(t, err) - assert.Equal(t, governance.ErrProposalIsDuplicate, err, k) - } } -func testSubmitInvalidProposal(t *testing.T) { +func testEnactmentTime(t *testing.T) { eng := getTestEngine(t) defer eng.ctrl.Finish() - partyID := "party1" + + party := eng.makeValidParty("a-valid-party", 1) + + eng.buf.EXPECT().Add(gomock.Any()).Times(2).Do(func(p types.Proposal) { + assert.Equal(t, types.Proposal_STATE_REJECTED, p.State) + assert.Equal(t, party.Id, p.PartyID) + }) + now := time.Now() - accErr := errors.New("account not found") - prop := types.Proposal{ - ID: "prop-1", - Reference: "test-prop-1", - PartyID: partyID, - State: types.Proposal_STATE_OPEN, - Terms: &types.ProposalTerms{ - ClosingTimestamp: now.Add(100 * time.Hour).Unix(), - EnactmentTimestamp: now.Add(240 * time.Hour).Unix(), - MinParticipationStake: 55, - }, - } - eng.accs.EXPECT().GetPartyTokenAccount(partyID).Times(1).Return(nil, accErr) + beforeClosingTime := eng.newOpenProposal(party.Id, now) + beforeClosingTime.Terms.EnactmentTimestamp = now.Unix() + assert.Less(t, beforeClosingTime.Terms.EnactmentTimestamp, beforeClosingTime.Terms.ClosingTimestamp) + err := eng.SubmitProposal(beforeClosingTime) + assert.Error(t, err) + assert.EqualError(t, err, governance.ErrProposalEnactTimeTooSoon.Error()) + + tooLate := eng.newOpenProposal(party.Id, now) + tooLate.Terms.EnactmentTimestamp = now.Add(3 * 365 * 24 * time.Hour).Unix() + err = eng.SubmitProposal(tooLate) + assert.Error(t, err) + assert.EqualError(t, err, governance.ErrProposalEnactTimeTooLate.Error()) + + atClosingTime := eng.newOpenProposal(party.Id, now) + atClosingTime.Terms.EnactmentTimestamp = atClosingTime.Terms.ClosingTimestamp + eng.accs.EXPECT().GetTotalTokens().Times(1).Return(uint64(1)) + eng.buf.EXPECT().Add(gomock.Any()).Times(1).Do(func(p types.Proposal) { + assert.Equal(t, types.Proposal_STATE_OPEN, p.State) + assert.Equal(t, party.Id, p.PartyID) + }) + err = eng.SubmitProposal(atClosingTime) +} + +func TestVoteValidation(t *testing.T) { + t.Run("Test proposal id on a vote", testVoteProposalID) + t.Run("Test voter stake validation", testVoterStake) + t.Run("Test voting on a declined proposal", testVotingDeclinedProposal) + t.Run("Test voting on a passed proposal", testVotingPassedProposal) + t.Run("Test proposal lifecycle - declined", testProposalDeclined) + t.Run("Test proposal lifecycle - passed", testProposalPassed) + t.Run("Test multiple proposal lifecycle", testMultipleProposalsLifecycle) +} + +func testVoteProposalID(t *testing.T) { + eng := getTestEngine(t) + defer eng.ctrl.Finish() + + voter := eng.makeValidParty("voter", 1) + + err := eng.AddVote(types.Vote{ + PartyID: voter.Id, + Value: types.Vote_VALUE_YES, // does not matter + ProposalID: "id-of-non-existent-proposal", + }) + assert.Error(t, err) + assert.EqualError(t, err, governance.ErrProposalNotFound.Error()) + + eng.accs.EXPECT().GetTotalTokens().Times(3).Return(uint64(2)) // 2 proposals + 1 valid vote + + emptyProposer := eng.makeValidParty("empty-proposer", 0) eng.buf.EXPECT().Add(gomock.Any()).Times(1).Do(func(p types.Proposal) { assert.Equal(t, types.Proposal_STATE_REJECTED, p.State) + assert.Equal(t, emptyProposer.Id, p.PartyID) + }) + rejectedProposal := eng.newOpenProposal(emptyProposer.Id, time.Now()) + err = eng.SubmitProposal(rejectedProposal) + assert.Error(t, err) + + err = eng.AddVote(types.Vote{ + PartyID: voter.Id, + Value: types.Vote_VALUE_NO, // does not matter + ProposalID: rejectedProposal.ID, + }) + assert.Error(t, err) + assert.EqualError(t, err, governance.ErrProposalNotFound.Error()) + + goodProposer := eng.makeValidParty("proposer", 1) + eng.buf.EXPECT().Add(gomock.Any()).Times(1).Do(func(p types.Proposal) { + assert.Equal(t, types.Proposal_STATE_OPEN, p.State) + assert.Equal(t, goodProposer.Id, p.PartyID) + }) + openProposal := eng.newOpenProposal(goodProposer.Id, time.Now()) + err = eng.SubmitProposal(openProposal) + assert.NoError(t, err) + + eng.vbuf.EXPECT().Add(gomock.Any()).Times(1).Do(func(vote types.Vote) { + assert.Equal(t, openProposal.ID, vote.ProposalID) + assert.Equal(t, voter.Id, vote.PartyID) + }) + err = eng.AddVote(types.Vote{ + PartyID: voter.Id, + Value: types.Vote_VALUE_YES, // does not matter + ProposalID: openProposal.ID, + }) + assert.NoError(t, err) +} + +func testVoterStake(t *testing.T) { + eng := getTestEngine(t) + defer eng.ctrl.Finish() + + eng.accs.EXPECT().GetTotalTokens().Times(3).Return(uint64(2)) + + proposer := eng.makeValidParty("proposer", 1) + openProposal := eng.newOpenProposal(proposer.Id, time.Now()) + eng.buf.EXPECT().Add(gomock.Any()).Times(1).Do(func(p types.Proposal) { + assert.Equal(t, types.Proposal_STATE_OPEN, p.State) + assert.Equal(t, proposer.Id, p.PartyID) + }) + err := eng.SubmitProposal(openProposal) + assert.NoError(t, err) + + voterNoAccount := "voter-no-account" + notFoundError := errors.New("account not found") + eng.accs.EXPECT().GetPartyTokenAccount(voterNoAccount).Times(1).Return(nil, notFoundError) + err = eng.AddVote(types.Vote{ + PartyID: voterNoAccount, + Value: types.Vote_VALUE_YES, // does not matter + ProposalID: openProposal.ID, + }) + assert.Error(t, err) + assert.EqualError(t, err, notFoundError.Error()) + + emptyAccount := eng.makeValidParty("empty-account", 0) + err = eng.AddVote(types.Vote{ + PartyID: emptyAccount.Id, + Value: types.Vote_VALUE_YES, // does not matter + ProposalID: openProposal.ID, + }) + assert.Error(t, err) + assert.EqualError(t, err, governance.ErrVoterInsufficientTokens.Error()) + + validAccount := eng.makeValidParty("valid-account", 1) + eng.vbuf.EXPECT().Add(gomock.Any()).Times(1).Do(func(vote types.Vote) { + assert.Equal(t, openProposal.ID, vote.ProposalID) + assert.Equal(t, validAccount.Id, vote.PartyID) + }) + err = eng.AddVote(types.Vote{ + PartyID: validAccount.Id, + Value: types.Vote_VALUE_YES, // does not matter + ProposalID: openProposal.ID, + }) + assert.NoError(t, err) +} + +func testVotingDeclinedProposal(t *testing.T) { + eng := getTestEngine(t) + defer eng.ctrl.Finish() + + eng.accs.EXPECT().GetTotalTokens().Times(2).Return(uint64(2)) + + proposer := eng.makeValidParty("proposer", 1) + declined := eng.newOpenProposal(proposer.Id, time.Now()) + eng.buf.EXPECT().Add(gomock.Any()).Times(1).Do(func(p types.Proposal) { + assert.Equal(t, types.Proposal_STATE_OPEN, p.State) + assert.Equal(t, proposer.Id, p.PartyID) + assert.Equal(t, declined.ID, p.ID) + }) + err := eng.SubmitProposal(declined) + assert.NoError(t, err) + + eng.buf.EXPECT().Add(gomock.Any()).Times(1).Do(func(p types.Proposal) { + assert.Equal(t, types.Proposal_STATE_DECLINED, p.State) + assert.Equal(t, declined.ID, p.ID) + }) + afterClose := time.Unix(declined.Terms.ClosingTimestamp, 0).Add(time.Hour) + accepted := eng.OnChainTimeUpdate(afterClose) + assert.Empty(t, accepted) // nothing was accepted + + voter := eng.makeValidPartyTimes("voter", 1, 0) + err = eng.AddVote(types.Vote{ + PartyID: voter.Id, + Value: types.Vote_VALUE_YES, // does not matter + ProposalID: declined.ID, + }) + assert.Error(t, err) + assert.EqualError(t, err, governance.ErrProposalNotFound.Error()) +} + +func testVotingPassedProposal(t *testing.T) { + eng := getTestEngine(t) + defer eng.ctrl.Finish() + + eng.accs.EXPECT().GetTotalTokens().Times(4).Return(uint64(9)) + + proposer := eng.makeValidParty("proposer", 1) + passed := eng.newOpenProposal(proposer.Id, time.Now()) + eng.buf.EXPECT().Add(gomock.Any()).Times(1).Do(func(p types.Proposal) { + assert.Equal(t, types.Proposal_STATE_OPEN, p.State) + assert.Equal(t, proposer.Id, p.PartyID) + assert.Equal(t, passed.ID, p.ID) + }) + err := eng.SubmitProposal(passed) + assert.NoError(t, err) + + voter1 := eng.makeValidPartyTimes("voter-1", 7, 2) + + eng.vbuf.EXPECT().Add(gomock.Any()).Times(1).Do(func(vote types.Vote) { + assert.Equal(t, passed.ID, vote.ProposalID) + assert.Equal(t, voter1.Id, vote.PartyID) + }) + err = eng.AddVote(types.Vote{ + PartyID: voter1.Id, + Value: types.Vote_VALUE_YES, // matters! + ProposalID: passed.ID, + }) + assert.NoError(t, err) + + afterClosing := time.Unix(passed.Terms.ClosingTimestamp, 0).Add(time.Second) + eng.buf.EXPECT().Add(gomock.Any()).Times(1).Do(func(p types.Proposal) { + assert.Equal(t, types.Proposal_STATE_PASSED, p.State) + assert.Equal(t, passed.ID, p.ID) + }) + eng.OnChainTimeUpdate(afterClosing) + + voter2 := eng.makeValidPartyTimes("voter2", 1, 0) + err = eng.AddVote(types.Vote{ + PartyID: voter2.Id, + Value: types.Vote_VALUE_NO, // does not matter + ProposalID: passed.ID, }) - err := eng.AddProposal(prop) assert.Error(t, err) + assert.EqualError(t, err, governance.ErrProposalPassed.Error()) + + afterEnactment := time.Unix(passed.Terms.EnactmentTimestamp, 0).Add(time.Second) + // no calculations, no state change, simply removed from governance engine + tobeEnacted := eng.OnChainTimeUpdate(afterEnactment) + assert.Len(t, tobeEnacted, 1) + assert.Equal(t, passed.ID, tobeEnacted[0].ID) + + err = eng.AddVote(types.Vote{ + PartyID: voter2.Id, + Value: types.Vote_VALUE_NO, // does not matter + ProposalID: passed.ID, + }) + assert.Error(t, err) + assert.EqualError(t, err, governance.ErrProposalNotFound.Error()) } -func testSubmitValidVoteSuccess(t *testing.T) { +func testProposalDeclined(t *testing.T) { eng := getTestEngine(t) defer eng.ctrl.Finish() - partyID := "party1" + now := time.Now() - acc := types.Account{ - Id: "acc-1", - Owner: partyID, - Balance: 1000, - Asset: collateral.TokenAsset, - } - partyID2 := "party2" - acc2 := types.Account{ - Id: "acc-2", - Owner: partyID2, - Balance: 100, - Asset: collateral.TokenAsset, - } - prop := types.Proposal{ - ID: "prop-1", - Reference: "test-prop-1", - PartyID: partyID, - State: types.Proposal_STATE_OPEN, - Terms: &types.ProposalTerms{ - ClosingTimestamp: now.Add(100 * time.Hour).Unix(), - EnactmentTimestamp: now.Add(240 * time.Hour).Unix(), - MinParticipationStake: 55, - }, - } - // we will call this getPartyTokenAccount twice - eng.accs.EXPECT().GetPartyTokenAccount(partyID).Times(2).Return(&acc, nil) - eng.accs.EXPECT().GetPartyTokenAccount(partyID2).Times(1).Return(&acc2, nil) - eng.buf.EXPECT().Add(gomock.Any()).Times(1) - err := eng.AddProposal(prop) + + eng.accs.EXPECT().GetTotalTokens().Times(4).Return(uint64(200)) + proposer := eng.makeValidParty("proposer", 100) + voter := eng.makeValidPartyTimes("voter", 100, 3) + + proposal := eng.newOpenProposal(proposer.Id, now) + eng.buf.EXPECT().Add(gomock.Any()).Times(1).Do(func(p types.Proposal) { + assert.Equal(t, types.Proposal_STATE_OPEN, p.State) + assert.Equal(t, proposer.Id, p.PartyID) + assert.Equal(t, proposal.ID, p.ID) + }) + err := eng.SubmitProposal(proposal) assert.NoError(t, err) - vote := types.Vote{ - PartyID: partyID, - Value: types.Vote_VALUE_YES, - ProposalID: prop.ID, - } - eng.vbuf.EXPECT().Add(gomock.Any()).Times(2) - assert.NoError(t, eng.AddVote(vote)) - vote.PartyID = partyID2 - vote.Value = types.Vote_VALUE_NO - assert.NoError(t, eng.AddVote(vote)) + + eng.vbuf.EXPECT().Add(gomock.Any()).Times(2).Do(func(vote types.Vote) { + assert.Equal(t, proposal.ID, vote.ProposalID) + assert.Equal(t, voter.Id, vote.PartyID) + }) + err = eng.AddVote(types.Vote{ + PartyID: voter.Id, + Value: types.Vote_VALUE_YES, // matters! + ProposalID: proposal.ID, + }) + assert.NoError(t, err) + + err = eng.AddVote(types.Vote{ + PartyID: voter.Id, + Value: types.Vote_VALUE_NO, // matters! + ProposalID: proposal.ID, + }) + assert.NoError(t, err) + + afterClosing := time.Unix(proposal.Terms.ClosingTimestamp, 0).Add(time.Second) + eng.buf.EXPECT().Add(gomock.Any()).Times(1).Do(func(p types.Proposal) { + assert.Equal(t, types.Proposal_STATE_DECLINED, p.State) + assert.Equal(t, proposal.ID, p.ID) + }) + eng.OnChainTimeUpdate(afterClosing) + + afterEnactment := time.Unix(proposal.Terms.EnactmentTimestamp, 0).Add(time.Second) + tobeEnacted := eng.OnChainTimeUpdate(afterEnactment) + assert.Empty(t, tobeEnacted) } -func testProposalAccepted(t *testing.T) { +func testProposalPassed(t *testing.T) { eng := getTestEngine(t) defer eng.ctrl.Finish() - partyID := "party1" + now := time.Now() - acc := types.Account{ - Id: "acc-1", - Owner: partyID, - Balance: 1000, + + eng.accs.EXPECT().GetTotalTokens().Times(4).Return(uint64(100)) + proposerVoter := eng.makeValidPartyTimes("proposer-and-voter", 100, 3) + + proposal := eng.newOpenProposal(proposerVoter.Id, now) + eng.buf.EXPECT().Add(gomock.Any()).Times(1).Do(func(p types.Proposal) { + assert.Equal(t, types.Proposal_STATE_OPEN, p.State) + assert.Equal(t, proposerVoter.Id, p.PartyID) + assert.Equal(t, proposal.ID, p.ID) + }) + err := eng.SubmitProposal(proposal) + assert.NoError(t, err) + + eng.vbuf.EXPECT().Add(gomock.Any()).Times(1).Do(func(vote types.Vote) { + assert.Equal(t, proposal.ID, vote.ProposalID) + assert.Equal(t, proposerVoter.Id, vote.PartyID) + }) + err = eng.AddVote(types.Vote{ + PartyID: proposerVoter.Id, + Value: types.Vote_VALUE_YES, // matters! + ProposalID: proposal.ID, + }) + assert.NoError(t, err) + + afterClosing := time.Unix(proposal.Terms.ClosingTimestamp, 0).Add(time.Second) + eng.buf.EXPECT().Add(gomock.Any()).Times(1).Do(func(p types.Proposal) { + assert.Equal(t, types.Proposal_STATE_PASSED, p.State) + assert.Equal(t, proposal.ID, p.ID) + }) + eng.OnChainTimeUpdate(afterClosing) + + modified := proposal + modified.State = types.Proposal_STATE_DECLINED + err = eng.SubmitProposal(proposal) + assert.Error(t, err) + assert.EqualError(t, err, governance.ErrProposalIsDuplicate.Error()) + + eng.makeValidPartyTimes(proposerVoter.Id, 0, 0) // effectively draining proposerVoter + afterEnactment := time.Unix(proposal.Terms.EnactmentTimestamp, 0).Add(time.Second) + tobeEnacted := eng.OnChainTimeUpdate(afterEnactment) + assert.Len(t, tobeEnacted, 1) + assert.Equal(t, proposal.ID, tobeEnacted[0].ID) +} + +func testMultipleProposalsLifecycle(t *testing.T) { + eng := getTestEngine(t) + defer eng.ctrl.Finish() + + partyA := "party-A" + eng.accs.EXPECT().GetTotalTokens().AnyTimes().Return(uint64(300)) + accountA := types.Account{ + Id: partyA + "-account", + Owner: partyA, + Balance: 200, Asset: collateral.TokenAsset, } - partyID2 := "party2" - acc2 := types.Account{ - Id: "acc-2", - Owner: partyID2, + eng.accs.EXPECT().GetPartyTokenAccount(accountA.Owner).AnyTimes().Return(&accountA, nil) + partyB := "party-B" + accountB := types.Account{ + Id: partyB + "-account", + Owner: partyB, Balance: 100, Asset: collateral.TokenAsset, } - closeTime := now.Add(100 * time.Hour) - totalTokens := acc.Balance + acc2.Balance - prop := types.Proposal{ - ID: "prop-1", - Reference: "test-prop-1", - PartyID: partyID, - State: types.Proposal_STATE_OPEN, - Terms: &types.ProposalTerms{ - ClosingTimestamp: closeTime.Unix(), - EnactmentTimestamp: closeTime.Unix(), - MinParticipationStake: 55, - }, + eng.accs.EXPECT().GetPartyTokenAccount(accountB.Owner).AnyTimes().Return(&accountB, nil) + + const howMany = 100 + now := time.Now() + + passed := map[string]*types.Proposal{} + declined := map[string]*types.Proposal{} + + var afterClosing time.Time + var afterEnactment time.Time + + for i := 0; i < howMany; i++ { + eng.buf.EXPECT().Add(gomock.Any()).Times(2).Do(func(p types.Proposal) { + assert.Equal(t, types.Proposal_STATE_OPEN, p.State) + }) + toBePassed := eng.newOpenProposal(partyA, now) + err := eng.SubmitProposal(toBePassed) + assert.NoError(t, err) + passed[toBePassed.ID] = &toBePassed + + toBeDeclined := eng.newOpenProposal(partyB, now) + err = eng.SubmitProposal(toBeDeclined) + assert.NoError(t, err) + declined[toBeDeclined.ID] = &toBeDeclined + + if i == 0 { + // all proposal terms are expected to be equal + afterClosing = time.Unix(toBePassed.Terms.ClosingTimestamp, 0).Add(time.Second) + afterEnactment = time.Unix(toBePassed.Terms.EnactmentTimestamp, 0).Add(time.Second) + } } - calls := 0 - states := []types.Proposal_State{ - types.Proposal_STATE_OPEN, - types.Proposal_STATE_PASSED, + assert.Len(t, passed, howMany) + assert.Len(t, declined, howMany) + + for id, _ := range passed { + eng.vbuf.EXPECT().Add(gomock.Any()).Times(2).Do(func(vote types.Vote) { + assert.Equal(t, id, vote.ProposalID) + }) + err := eng.AddVote(types.Vote{ + PartyID: partyA, + Value: types.Vote_VALUE_YES, // matters! + ProposalID: id, + }) + assert.NoError(t, err) + err = eng.AddVote(types.Vote{ + PartyID: partyB, + Value: types.Vote_VALUE_NO, // matters! + ProposalID: id, + }) + assert.NoError(t, err) } - eng.buf.EXPECT().Add(gomock.Any()).Times(2).Do(func(p types.Proposal) { - assert.Equal(t, states[calls], p.State) - calls++ + for id, _ := range declined { + eng.vbuf.EXPECT().Add(gomock.Any()).Times(2).Do(func(vote types.Vote) { + assert.Equal(t, id, vote.ProposalID) + }) + err := eng.AddVote(types.Vote{ + PartyID: partyA, + Value: types.Vote_VALUE_NO, // matters! + ProposalID: id, + }) + assert.NoError(t, err) + err = eng.AddVote(types.Vote{ + PartyID: partyB, + Value: types.Vote_VALUE_YES, // matters! + ProposalID: id, + }) + assert.NoError(t, err) + } + + var howManyPassed, howManyDeclined int + eng.buf.EXPECT().Add(gomock.Any()).Times(howMany * 2).Do(func(p types.Proposal) { + if p.State == types.Proposal_STATE_PASSED { + _, found := passed[p.ID] + assert.True(t, found, "passed proposal is in the passed collection") + howManyPassed++ + } else if p.State == types.Proposal_STATE_DECLINED { + _, found := declined[p.ID] + assert.True(t, found, "declined proposal is in the declined collection") + howManyDeclined++ + } else { + assert.FailNow(t, "unexpected proposal state") + } }) - eng.accs.EXPECT().GetPartyTokenAccount(partyID).Times(1).Return(&acc, nil) // only stake holders can propose - err := eng.AddProposal(prop) - assert.NoError(t, err) - vote := types.Vote{ - PartyID: partyID, - Value: types.Vote_VALUE_YES, - ProposalID: prop.ID, + eng.OnChainTimeUpdate(afterClosing) + assert.Equal(t, howMany, howManyPassed) + assert.Equal(t, howMany, howManyDeclined) + + tobeEnacted := eng.OnChainTimeUpdate(afterEnactment) + assert.Len(t, tobeEnacted, howMany) + for i := 0; i < howMany; i++ { + _, found := passed[tobeEnacted[i].ID] + assert.True(t, found) } - eng.vbuf.EXPECT().Add(gomock.Any()).Times(2) - eng.accs.EXPECT().GetPartyTokenAccount(partyID).Times(1).Return(&acc, nil) // only stake holders can vote - assert.NoError(t, eng.AddVote(vote)) - - vote.PartyID = partyID2 - vote.Value = types.Vote_VALUE_NO - eng.accs.EXPECT().GetPartyTokenAccount(partyID2).Times(1).Return(&acc2, nil) // only stake holders can vote - assert.NoError(t, eng.AddVote(vote)) - - eng.accs.EXPECT().GetTotalTokens().Times(1).Return(totalTokens) - eng.accs.EXPECT().GetPartyTokenAccount(partyID).Times(1).Return(&acc, nil) // to count votes - eng.accs.EXPECT().GetPartyTokenAccount(partyID2).Times(1).Return(&acc2, nil) // to count votes - // simulate block time update triggering end of proposal vote - accepted := eng.OnChainTimeUpdate(closeTime.Add(time.Hour)) - assert.NotEmpty(t, accepted) } func getTestEngine(t *testing.T) *tstEngine { @@ -251,7 +665,8 @@ func getTestEngine(t *testing.T) *tstEngine { accs := mocks.NewMockAccounts(ctrl) buf := mocks.NewMockBuffer(ctrl) vbuf := mocks.NewMockVoteBuf(ctrl) - eng := governance.NewEngine(logging.NewTestLogger(), cfg, governance.DefaultNetworkParameters(), accs, buf, vbuf, time.Now()) + log := logging.NewTestLogger() + eng := governance.NewEngine(log, cfg, governance.DefaultNetworkParameters(log), accs, buf, vbuf, time.Now()) return &tstEngine{ Engine: eng, ctrl: ctrl, @@ -260,3 +675,98 @@ func getTestEngine(t *testing.T) *tstEngine { vbuf: vbuf, } } + +func newValidMarketTerms() *types.ProposalTerms_NewMarket { + return &types.ProposalTerms_NewMarket{ + NewMarket: &types.NewMarket{ + Changes: &types.Market{ + Id: "a-unit-test-market", + DecimalPlaces: 5, + Name: "a-unit-test-market-name", + TradingMode: &types.Market_Continuous{ + Continuous: &types.ContinuousTrading{ + TickSize: 0, + }, + }, + TradableInstrument: &types.TradableInstrument{ + Instrument: &types.Instrument{ + Id: "Crypto/GBPVUSD/Futures/Jun20", + Code: "CRYPTO:GBPVUSD/JUN20", + Name: "June 2020 GBP vs VUSD future", + BaseName: "GBP", + QuoteName: "VUSD", + Metadata: &types.InstrumentMetadata{ + Tags: []string{"asset_class:fx/crypto", "product:futures"}, + }, + InitialMarkPrice: 123321, + Product: &types.Instrument_Future{ + Future: &types.Future{ + Maturity: "2030-06-30T22:59:59Z", + Asset: "VUSD", + Oracle: &types.Future_EthereumEvent{ + EthereumEvent: &types.EthereumEvent{ + ContractID: "0x0B484706fdAF3A4F24b2266446B1cb6d648E3cC1", + Event: "price_changed", + }, + }, + }, + }, + }, + MarginCalculator: &types.MarginCalculator{ + ScalingFactors: &types.ScalingFactors{ + InitialMargin: 1.2, + CollateralRelease: 1.4, + SearchLevel: 1.1, + }, + }, + RiskModel: &types.TradableInstrument_LogNormalRiskModel{ + LogNormalRiskModel: &types.LogNormalRiskModel{ + RiskAversionParameter: 0.01, + Tau: 0.00011407711613050422, + Params: &types.LogNormalModelParams{ + Mu: 0, + R: 0.016, + Sigma: 0.09, + }, + }, + }, + }, + }, + }, + } +} + +func (e *tstEngine) makeValidPartyTimes(partyID string, balance uint64, times int) *types.Party { + account := types.Account{ + Id: partyID + "-account", + Owner: partyID, + Balance: balance, + Asset: collateral.TokenAsset, + } + e.accs.EXPECT().GetPartyTokenAccount(partyID).Times(times).Return(&account, nil) + return &types.Party{Id: partyID} +} + +func (e *tstEngine) makeValidParty(partyID string, balance uint64) *types.Party { + return e.makeValidPartyTimes(partyID, balance, 1) +} + +func (e *tstEngine) newProposalID(partyID string) string { + e.proposalCounter++ + return fmt.Sprintf("proposal-id-%d", e.proposalCounter) +} + +func (e *tstEngine) newOpenProposal(partyID string, now time.Time) types.Proposal { + id := e.newProposalID(partyID) + return types.Proposal{ + ID: id, + Reference: "ref-" + id, + PartyID: partyID, + State: types.Proposal_STATE_OPEN, + Terms: &types.ProposalTerms{ + ClosingTimestamp: now.Add(48 * time.Hour).Unix(), + EnactmentTimestamp: now.Add(2 * 48 * time.Hour).Unix(), + Change: newValidMarketTerms(), //TODO: add more variaty here (when available) + }, + } +} diff --git a/governance/mocks/plugin_mock.go b/governance/mocks/plugin_mock.go index 4236a248191..5698303a5d9 100644 --- a/governance/mocks/plugin_mock.go +++ b/governance/mocks/plugin_mock.go @@ -5,10 +5,9 @@ package mocks import ( - reflect "reflect" - proto "code.vegaprotocol.io/vega/proto" gomock "github.com/golang/mock/gomock" + reflect "reflect" ) // MockPlugin is a mock of Plugin interface diff --git a/governance/networkparams.go b/governance/networkparams.go index c4b7e5f484e..dfe0bfbee35 100644 --- a/governance/networkparams.go +++ b/governance/networkparams.go @@ -1,9 +1,10 @@ package governance import ( - "fmt" "strconv" "time" + + "code.vegaprotocol.io/vega/logging" ) const ( @@ -17,7 +18,10 @@ var ( MaxClose = "" MinEnact = "" MaxEnact = "" - MinParticipationStake = "" + RequiredParticipation = "" + RequiredMajority = "" + MinProposerBalance = "" + MinVoterBalance = "" ) const ( @@ -30,72 +34,208 @@ const ( defaultMinEnact = 2 * day // must be >= minClose // defaultMaxEnact is the hardcoded maximum enactment offset duration defaultMaxEnact = 1 * year - // defaultMinParticipationStake is hardcoded minimum participation stake percent - defaultMinParticipationStake = 1 + // defaultRequiredParticipation is hardcoded participation level required for any proposal to pass (from `0` to `1`) + defaultRequiredParticipation = 0.00001 + // defaultRequiredMajority is hardcoded majority level required for any proposal to pass (from `0.5` to `1`) + defaultRequiredMajority = 0.66 + // defaultProposerBalance is hardcoded minimum balance required for a party + // to be able to submit a new proposal (greater than `0` to `1`) + defaultMinProposerBalance = 0.00001 + // defaultMinVoterBalance is hardcoded minimum balance required for a party + // to be able to cast a vote (greater than `0` to `1`). + defaultMinVoterBalance = 0.00001 ) -// NetworkParameters stores governance network parameters +// ProposalParameters stores proposal specific parameters +type ProposalParameters struct { + MinClose time.Duration + MaxClose time.Duration + MinEnact time.Duration + MaxEnact time.Duration + RequiredParticipation float32 + RequiredMajority float32 + MinProposerBalance float32 + MinVoterBalance float32 +} + +// NetworkParameters stores network parameters per proposal type type NetworkParameters struct { - minClose time.Duration - maxClose time.Duration - minEnact time.Duration - maxEnact time.Duration - minParticipationStake uint64 + newMarkets ProposalParameters } // DefaultNetworkParameters returns default, hardcoded, network parameters -func DefaultNetworkParameters() *NetworkParameters { +func DefaultNetworkParameters(log *logging.Logger) *NetworkParameters { + return &NetworkParameters{ + newMarkets: defaultNewMarketParameters(log), + } +} + +func defaultNewMarketParameters(log *logging.Logger) ProposalParameters { var err error - result := &NetworkParameters{ - minClose: defaultMinClose, - maxClose: defaultMaxClose, - minEnact: defaultMinEnact, - maxEnact: defaultMaxEnact, - minParticipationStake: defaultMinParticipationStake, + result := ProposalParameters{ + MinClose: defaultMinClose, + MaxClose: defaultMaxClose, + MinEnact: defaultMinEnact, + MaxEnact: defaultMaxEnact, + RequiredParticipation: defaultRequiredParticipation, + RequiredMajority: defaultRequiredMajority, + MinProposerBalance: defaultMinProposerBalance, + MinVoterBalance: defaultMinVoterBalance, } + if len(MinClose) > 0 { - result.minClose, err = time.ParseDuration(MinClose) + result.MinClose, err = time.ParseDuration(MinClose) if err != nil { - panic(fmt.Sprintf("Failed to parse time duration: %s", MinClose)) + log.Fatal( + "Failed to parse new market network parameter", + logging.String("MinClose", MinClose), + logging.Error(err), + ) } } if len(MaxClose) > 0 { - result.maxClose, err = time.ParseDuration(MaxClose) + result.MaxClose, err = time.ParseDuration(MaxClose) if err != nil { - panic(fmt.Sprintf("Failed to parse time duration: %s", MaxClose)) + log.Fatal( + "Failed to parse new market network parameter", + logging.String("MaxClose", MaxClose), + logging.Error(err), + ) } } if len(MinEnact) > 0 { - result.minEnact, err = time.ParseDuration(MinEnact) + result.MinEnact, err = time.ParseDuration(MinEnact) if err != nil { - panic(fmt.Sprintf("Failed to parse time duration: %s", MinEnact)) + log.Fatal( + "Failed to parse new market network parameter", + logging.String("MinEnact", MinEnact), + logging.Error(err), + ) } } if len(MaxEnact) > 0 { - result.maxEnact, err = time.ParseDuration(MaxEnact) + result.MaxEnact, err = time.ParseDuration(MaxEnact) if err != nil { - panic(fmt.Sprintf("Failed to parse time duration: %s", MaxEnact)) + log.Fatal( + "Failed to parse new market network parameter", + logging.String("MaxEnact", MaxEnact), + logging.Error(err), + ) } } - if len(MinParticipationStake) > 0 { - result.minParticipationStake, err = strconv.ParseUint(MinParticipationStake, 10, 64) + if len(RequiredParticipation) > 0 { + levelValue, err := strconv.ParseFloat(RequiredParticipation, 32) if err != nil { - panic(fmt.Sprintf("Failed to parse time integer: %s", MinParticipationStake)) + log.Fatal( + "Failed to parse new market network parameter", + logging.String("RequiredParticipation", RequiredParticipation), + logging.Error(err), + ) + } + if levelValue < 0 { + log.Fatal( + "New market network parameter is invalid (negative)", + logging.String("RequiredParticipation", RequiredParticipation), + ) } - if result.minParticipationStake > 100 { - panic(fmt.Sprintf("Invalid MinParticipationStake (over 100): %d", result.minParticipationStake)) + if levelValue > 1 { + log.Fatal( + "New market network parameter is invalid (over 1)", + logging.String("RequiredParticipation", RequiredParticipation), + ) } + result.RequiredParticipation = float32(levelValue) + } + if len(RequiredMajority) > 0 { + levelValue, err := strconv.ParseFloat(RequiredMajority, 32) + if err != nil { + log.Fatal( + "Failed to parse new market network parameter", + logging.String("RequiredMajority", RequiredMajority), + logging.Error(err), + ) + } + if levelValue < 0.5 { + log.Fatal( + "New market network parameter is invalid (less than 0.5)", + logging.String("RequiredMajority", RequiredMajority), + ) + } + if levelValue > 1 { + log.Fatal( + "New market network parameter is invalid (over 1)", + logging.String("RequiredMajority", RequiredMajority), + ) + } + result.RequiredMajority = float32(levelValue) + } + if len(MinProposerBalance) > 0 { + levelValue, err := strconv.ParseFloat(MinProposerBalance, 32) + if err != nil { + log.Fatal( + "Failed to parse new market network parameter", + logging.String("MinProposerBalance", MinProposerBalance), + logging.Error(err), + ) + } + if levelValue <= 0 { + log.Fatal( + "New market network parameter is invalid (less or equal than 0)", + logging.String("MinProposerBalance", MinProposerBalance), + ) + } + if levelValue > 1 { + log.Fatal( + "New market network parameter is invalid (over 1)", + logging.String("MinProposerBalance", MinProposerBalance), + ) + } + result.MinProposerBalance = float32(levelValue) + } + if len(MinVoterBalance) > 0 { + levelValue, err := strconv.ParseFloat(MinVoterBalance, 32) + if err != nil { + log.Fatal( + "Failed to parse new market network parameter", + logging.String("MinVoterBalance", MinVoterBalance), + logging.Error(err), + ) + } + if levelValue <= 0 { + log.Fatal( + "New market network parameter is invalid (less or equal than 0)", + logging.String("MinVoterBalance", MinVoterBalance), + ) + } + if levelValue > 1 { + log.Fatal( + "New market network parameter is invalid (over 1)", + logging.String("MinVoterBalance", MinVoterBalance), + ) + } + result.MinVoterBalance = float32(levelValue) } - result.maxClose = max(result.maxClose, result.minClose) // maxClose must be >= minClose - result.minEnact = max(result.minEnact, result.minClose) // minEnact must be >= minClose - result.maxEnact = max(result.maxEnact, result.minEnact) // maxEnact must be >= minEnact - return result -} - -func max(left, right time.Duration) time.Duration { - if left > right { - return left + if result.MaxClose < result.MinClose { + log.Fatal( + "New market MaxClose network parameter is less than MinClose", + logging.String("MaxClose", result.MaxClose.String()), + logging.String("MinClose", result.MinClose.String()), + ) } - return right + if result.MaxEnact < result.MinEnact { + log.Fatal( + "New market MaxEnact network parameter is less than MinEnact", + logging.String("MaxEnact", result.MaxEnact.String()), + logging.String("MinEnact", result.MinEnact.String()), + ) + } + if result.MinEnact < result.MinClose { + log.Fatal( + "New market MinEnact network parameter is less than MinClose", + logging.String("MinEnact", result.MinEnact.String()), + logging.String("MinClose", result.MinClose.String()), + ) + } + return result } diff --git a/governance/service.go b/governance/service.go index f473f0d200b..773b5effebb 100644 --- a/governance/service.go +++ b/governance/service.go @@ -276,6 +276,7 @@ func (s *Svc) GetNewAssetProposals(inState *types.Proposal_State) []*types.Gover func (s *Svc) PrepareProposal( ctx context.Context, party string, reference string, terms *types.ProposalTerms, ) (*types.Proposal, error) { + if err := s.validateTerms(terms); err != nil { return nil, err } diff --git a/governance/service_test.go b/governance/service_test.go index 72f66e1f937..5aaf54256e2 100644 --- a/governance/service_test.go +++ b/governance/service_test.go @@ -112,9 +112,8 @@ func testPrepareProposalNormal(t *testing.T) { }, } terms := types.ProposalTerms{ - ClosingTimestamp: time.Now().Add(time.Hour * 24 * 2).UTC().Unix(), - EnactmentTimestamp: time.Now().Add(time.Hour * 24 * 60).UTC().Unix(), - MinParticipationStake: 50, + ClosingTimestamp: time.Now().Add(time.Hour * 24 * 2).UTC().Unix(), + EnactmentTimestamp: time.Now().Add(time.Hour * 24 * 60).UTC().Unix(), Change: &types.ProposalTerms_UpdateNetwork{ UpdateNetwork: &updateNetwork, }, diff --git a/integration/core_test.go b/integration/core_test.go index 764aad95cca..99c13cdbd06 100644 --- a/integration/core_test.go +++ b/integration/core_test.go @@ -136,7 +136,6 @@ func theMarket(mSetup *gherkin.DataTable) error { mktsetup.party, // party-engine here! mkt, mktsetup.candles, - mktsetup.trades, mktsetup.marginLevelsBuf, NewSettlementStub(), time.Now(), diff --git a/integration/execution_layer_test.go b/integration/execution_layer_test.go index d01a1851e72..bff90302ae3 100644 --- a/integration/execution_layer_test.go +++ b/integration/execution_layer_test.go @@ -70,7 +70,7 @@ func theFollowingTraders(arg1 *gherkin.DataTable) error { Amount: u64val(row, 1), } - err := execsetup.engine.NotifyTraderAccount(context.TODO(), ¬if) + err := execsetup.engine.NotifyTraderAccount(context.Background(), ¬if) if err != nil { return err } @@ -180,7 +180,7 @@ func theMakesADepositOfIntoTheAccount(trader, amountstr, asset string) error { Amount: amount, } - err := execsetup.engine.NotifyTraderAccount(context.TODO(), ¬if) + err := execsetup.engine.NotifyTraderAccount(context.Background(), ¬if) if err != nil { return err } @@ -211,7 +211,7 @@ func theWithdrawFromTheAccount(trader, amountstr, asset string) error { Asset: asset, } - err := execsetup.engine.Withdraw(context.TODO(), ¬if) + err := execsetup.engine.Withdraw(context.Background(), ¬if) if err != nil { return err } @@ -249,7 +249,7 @@ func tradersPlaceFollowingOrders(orders *gherkin.DataTable) error { TimeInForce: tif, CreatedAt: time.Now().UnixNano(), } - result, err := execsetup.engine.SubmitOrder(context.TODO(), &order) + result, err := execsetup.engine.SubmitOrder(context.Background(), &order) if err != nil { return fmt.Errorf("unable to place order, err=%v (trader=%v)", err, val(row, 0)) } @@ -291,7 +291,7 @@ func missingTradersPlaceFollowingOrdersWithReferences(orders *gherkin.DataTable) CreatedAt: time.Now().UnixNano(), Reference: val(row, 8), } - if _, err := execsetup.engine.SubmitOrder(context.TODO(), &order); err == nil { + if _, err := execsetup.engine.SubmitOrder(context.Background(), &order); err == nil { return fmt.Errorf("expected trader %s to not exist", order.PartyID) } } @@ -328,7 +328,7 @@ func tradersPlaceFollowingOrdersWithReferences(orders *gherkin.DataTable) error CreatedAt: time.Now().UnixNano(), Reference: val(row, 8), } - result, err := execsetup.engine.SubmitOrder(context.TODO(), &order) + result, err := execsetup.engine.SubmitOrder(context.Background(), &order) if err != nil { return err } @@ -356,7 +356,7 @@ func tradersCancelsTheFollowingFilledOrdersReference(refs *gherkin.DataTable) er MarketID: o.MarketID, } - if _, err = execsetup.engine.CancelOrder(context.TODO(), &cancel); err == nil { + if _, err = execsetup.engine.CancelOrder(context.Background(), &cancel); err == nil { return fmt.Errorf("successfully cancelled order for trader %s (reference %s)", o.PartyID, o.Reference) } } @@ -381,7 +381,7 @@ func missingTradersCancelsTheFollowingOrdersReference(refs *gherkin.DataTable) e MarketID: o.MarketID, } - if _, err = execsetup.engine.CancelOrder(context.TODO(), &cancel); err == nil { + if _, err = execsetup.engine.CancelOrder(context.Background(), &cancel); err == nil { return fmt.Errorf("successfully cancelled order for trader %s (reference %s)", o.PartyID, o.Reference) } } @@ -406,7 +406,7 @@ func tradersCancelsTheFollowingOrdersReference(refs *gherkin.DataTable) error { MarketID: o.MarketID, } - _, err = execsetup.engine.CancelOrder(context.TODO(), &cancel) + _, err = execsetup.engine.CancelOrder(context.Background(), &cancel) if err != nil { return fmt.Errorf("unable to cancel order for trader %s, reference %s", o.PartyID, o.Reference) } @@ -563,7 +563,7 @@ func tradersCannotPlaceTheFollowingOrdersAnymore(orders *gherkin.DataTable) erro TimeInForce: proto.Order_TIF_GTT, CreatedAt: time.Now().UnixNano(), } - _, err := execsetup.engine.SubmitOrder(context.TODO(), &order) + _, err := execsetup.engine.SubmitOrder(context.Background(), &order) if err == nil { return fmt.Errorf("expected error (%v) but got (%v)", val(row, 6), err) } @@ -614,6 +614,11 @@ func tradersPlaceFollowingFailingOrders(orders *gherkin.DataTable) error { continue } + oty, err := ordertypeval(row, 6) + if err != nil { + return err + } + order := proto.Order{ Id: uuid.NewV4().String(), MarketID: val(row, 1), @@ -623,11 +628,11 @@ func tradersPlaceFollowingFailingOrders(orders *gherkin.DataTable) error { Size: u64val(row, 3), Remaining: u64val(row, 3), ExpiresAt: time.Now().Add(24 * time.Hour).UnixNano(), - Type: proto.Order_TYPE_LIMIT, + Type: oty, TimeInForce: proto.Order_TIF_GTT, CreatedAt: time.Now().UnixNano(), } - _, err := execsetup.engine.SubmitOrder(context.TODO(), &order) + _, err = execsetup.engine.SubmitOrder(context.Background(), &order) if err == nil { return fmt.Errorf("expected error (%v) but got (%v)", val(row, 5), err) } @@ -733,7 +738,8 @@ func theFollowingNetworkTradesHappened(trades *gherkin.DataTable) error { } ok := false party, side, volume := val(row, 0), sideval(row, 1), u64val(row, 2) - for _, v := range execsetup.trades.data { + data := execsetup.broker.getTrades() + for _, v := range data { if (v.Buyer == party || v.Seller == party) && v.Aggressor == side && v.Size == volume { ok = true break @@ -757,10 +763,10 @@ func theFollowingTradesHappened(trades *gherkin.DataTable) error { } ok := false buyer, seller, price, volume := val(row, 0), val(row, 1), u64val(row, 2), u64val(row, 3) - for _, v := range execsetup.trades.data { + data := execsetup.broker.getTrades() + for _, v := range data { if v.Buyer == buyer && v.Seller == seller && v.Price == price && v.Size == volume { - ok = true - break + return nil } } @@ -809,7 +815,7 @@ func tradersAmendsTheFollowingOrdersReference(refs *gherkin.DataTable) error { TimeInForce: tif, } - _, err = execsetup.engine.AmendOrder(context.TODO(), &amend) + _, err = execsetup.engine.AmendOrder(context.Background(), &amend) if err != nil && success { return fmt.Errorf("expected to succeed amending but failed for trader %s (reference %s, err %v)", o.PartyID, o.Reference, err) } @@ -971,7 +977,8 @@ func executedTrades(trades *gherkin.DataTable) error { size := u64val(row, 2) counterparty := val(row, 3) var found bool = false - for _, v := range execsetup.trades.data { + data := execsetup.broker.getTrades() + for _, v := range data { if v.Buyer == trader && v.Seller == counterparty && v.Price == price && v.Size == size { found = true break diff --git a/integration/features/1779-cannot-place-network-order.feature b/integration/features/1779-cannot-place-network-order.feature new file mode 100644 index 00000000000..493c48ffc4c --- /dev/null +++ b/integration/features/1779-cannot-place-network-order.feature @@ -0,0 +1,19 @@ +Feature: Cannot place an network order + + Background: + Given the insurance pool initial balance for the markets is "0": + And the executon engine have these markets: + | name | baseName | quoteName | asset | markprice | risk model | lamd/long | tau/short | mu | r | sigma | release factor | initial factor | search factor | settlementPrice | + | ETH/DEC19 | BTC | ETH | ETH | 1000 | simple | 0.11 | 0.1 | 0 | 0 | 0 | 1.4 | 1.2 | 1.1 | 42 | + + Scenario: an order is rejected if a trader try to place an order with type NETWORK + Given the following traders: + | name | amount | + | trader1 | 1 | + Then I Expect the traders to have new general account: + | name | asset | + | trader1 | ETH | + And "trader1" general accounts balance is "1" + Then traders place following failing orders: + | trader | id | type | volume | price | error | type | + | trader1 | ETH/DEC19 | sell | 1 | 1000 | invalid order type | TYPE_NETWORK | diff --git a/integration/features/margins.feature b/integration/features/margins.feature index 9804cdec4e5..4ce6fb4dd6a 100644 --- a/integration/features/margins.feature +++ b/integration/features/margins.feature @@ -33,8 +33,8 @@ Feature: Test trader accounts | trader1 | ETH | And "trader1" general accounts balance is "1" Then traders place following failing orders: - | trader | id | type | volume | price | error | - | trader1 | ETH/DEC19 | sell | 1 | 1000 | margin check failed | + | trader | id | type | volume | price | error | type | + | trader1 | ETH/DEC19 | sell | 1 | 1000 | margin check failed | TYPE_LIMIT | Then the following orders are rejected: | trader | id | reason | | trader1 | ETH/DEC19 | ORDER_ERROR_MARGIN_CHECK_FAILED | diff --git a/integration/setup_test.go b/integration/setup_test.go index 137724b7156..a848587b2a0 100644 --- a/integration/setup_test.go +++ b/integration/setup_test.go @@ -52,7 +52,6 @@ type marketTestSetup struct { core *execution.Market party *execution.Party candles *mocks.MockCandleBuf - trades *tradeStub accounts *accStub marginLevelsBuf *marginsStub settle *SettleStub @@ -82,7 +81,6 @@ func getMarketTestSetup(market *proto.Market) *marketTestSetup { lossBuf.EXPECT().Add(gomock.Any()).AnyTimes() lossBuf.EXPECT().Flush().AnyTimes() broker := NewBrokerStub() - trades := NewTradeStub() // this can happen any number of times, just set the mock up to accept all of them // Over time, these mocks will be replaced with stubs that store all elements to a map @@ -101,7 +99,6 @@ func getMarketTestSetup(market *proto.Market) *marketTestSetup { market: market, ctrl: ctrl, candles: candles, - trades: trades, marginLevelsBuf: marginLevelsBuf, settle: NewSettlementStub(), lossSoc: lossBuf, @@ -121,7 +118,6 @@ type executionTestSetup struct { log *logging.Logger ctrl *gomock.Controller candles *mocks.MockCandleBuf - trades *tradeStub markets *mocks.MockMarketBuf timesvc *timeStub marketdata *mocks.MockMarketDataBuf @@ -165,7 +161,6 @@ func getExecutionTestSetup(startTime time.Time, mkts []proto.Market) *executionT execsetup.cfg.InsurancePoolInitialBalance = execsetup.InsurancePoolInitialBalance execsetup.log = logging.NewTestLogger() execsetup.candles = mocks.NewMockCandleBuf(ctrl) - execsetup.trades = NewTradeStub() execsetup.settle = buffer.NewSettlement() execsetup.markets = mocks.NewMockMarketBuf(ctrl) execsetup.accs = map[string][]account{} @@ -186,7 +181,7 @@ func getExecutionTestSetup(startTime time.Time, mkts []proto.Market) *executionT execsetup.candles.EXPECT().AddTrade(gomock.Any()).AnyTimes() execsetup.markets.EXPECT().Flush().AnyTimes().Return(nil) - execsetup.engine = execution.NewEngine(execsetup.log, execsetup.cfg, execsetup.timesvc, execsetup.trades, execsetup.candles, execsetup.markets, execsetup.marketdata, execsetup.marginLevelsBuf, execsetup.settle, execsetup.lossSoc, execsetup.proposal, execsetup.votes, mkts, execsetup.broker) + execsetup.engine = execution.NewEngine(execsetup.log, execsetup.cfg, execsetup.timesvc, execsetup.candles, execsetup.markets, execsetup.marketdata, execsetup.marginLevelsBuf, execsetup.settle, execsetup.lossSoc, execsetup.proposal, execsetup.votes, mkts, execsetup.broker) // instanciate position plugin execsetup.positionPlugin = plugins.NewPositions(execsetup.settle, execsetup.lossSoc) diff --git a/integration/stubs_test.go b/integration/stubs_test.go index 4e174c64e99..2ebe7c0c9a8 100644 --- a/integration/stubs_test.go +++ b/integration/stubs_test.go @@ -76,6 +76,23 @@ func (b *brokerStub) GetOrderEvents() []events.Order { return ret } +func (b *brokerStub) GetTradeEvents() []events.Trade { + batch := b.GetBatch(events.TradeEvent) + if len(batch) == 0 { + return nil + } + ret := make([]events.Trade, 0, len(batch)) + for _, e := range batch { + switch et := e.(type) { + case *events.Trade: + ret = append(ret, *et) + case events.Trade: + ret = append(ret, et) + } + } + return ret +} + func (b *brokerStub) GetAccounts() []events.Acc { batch := b.GetBatch(events.AccountEvent) if len(batch) == 0 { @@ -153,6 +170,15 @@ func (b *brokerStub) getByReference(party, ref string) (proto.Order, error) { return proto.Order{}, fmt.Errorf("no order for party %v and referrence %v", party, ref) } +func (b *brokerStub) getTrades() []proto.Trade { + data := b.GetTradeEvents() + trades := make([]proto.Trade, 0, len(data)) + for _, t := range data { + trades = append(trades, t.Trade()) + } + return trades +} + func (b *brokerStub) ResetType(t events.Type) { b.mu.Lock() b.data[t] = []events.Event{} diff --git a/matching/orderbook.go b/matching/orderbook.go index f274905a984..2df7fb6a708 100644 --- a/matching/orderbook.go +++ b/matching/orderbook.go @@ -379,6 +379,7 @@ func (b *OrderBook) RemoveExpiredOrders(expirationTimestamp int64) []types.Order // when they get cancelled as this would required unnecessary computation that // can be delayed for later. order.Status = types.Order_STATUS_EXPIRED + order.UpdatedAt = expirationTimestamp out = append(out, *order) } } diff --git a/monitoring/status_test.go b/monitoring/status_test.go index 8e6575ba16a..16810c896fa 100644 --- a/monitoring/status_test.go +++ b/monitoring/status_test.go @@ -33,7 +33,7 @@ func TestAppStatus(t *testing.T) { CatchingUp: false, }, NodeInfo: p2p.DefaultNodeInfo{ - Version: "0.32.9", + Version: "0.33.5", }, } diff --git a/monitoring/version.go b/monitoring/version.go index c70bdbf712a..b01189ab30a 100644 --- a/monitoring/version.go +++ b/monitoring/version.go @@ -8,8 +8,8 @@ import ( ) var ( - minVersion = semver.MustParse("0.32.9") - maxVersion = semver.MustParse("0.33.0") + minVersion = semver.MustParse("0.33.5") + maxVersion = semver.MustParse("0.34.0") ) var defaultChainVersion = ChainVersion{ diff --git a/orders/service.go b/orders/service.go index dcad483c1e8..58f1a30f673 100644 --- a/orders/service.go +++ b/orders/service.go @@ -46,6 +46,8 @@ var ( ErrNoSide = errors.New("no value has been set for the side") // ErrNoType no value has been set for the type ErrNoType = errors.New("no value has been set for the type") + // ErrUnAuthorizedOrderType order type is not allowed (most likely NETWORK) + ErrUnAuthorizedOrderType = errors.New("unauthorized order type") ) // TimeService ... @@ -177,6 +179,9 @@ func (s *Svc) validateOrderSubmission(sub *types.OrderSubmission) error { if sub.Type == types.Order_TYPE_LIMIT && sub.Price == 0 { return ErrInvalidPriceForLimitOrder } + if sub.Type == types.Order_TYPE_NETWORK { + return ErrUnAuthorizedOrderType + } return nil } diff --git a/orders/service_test.go b/orders/service_test.go index 3c2f307e09c..487e9364dbb 100644 --- a/orders/service_test.go +++ b/orders/service_test.go @@ -58,6 +58,7 @@ func TestPrepareCancelOrder(t *testing.T) { func TestCreateOrder(t *testing.T) { t.Run("Create order - successful", testOrderSuccess) t.Run("Create order - error expiry set for non gtt", testCreateOrderFailExpirySetForNonGTT) + t.Run("Create order - error use network order type", testCreateOrderFailNetworkOrderType) } func TestGetByOrderID(t *testing.T) { @@ -155,6 +156,22 @@ func testCreateOrderFailExpirySetForNonGTT(t *testing.T) { assert.NoError(t, err) } +func testCreateOrderFailNetworkOrderType(t *testing.T) { + // now + now := vegatime.Now() + // expires 2 hours from now + expires := now.Add(time.Hour * 2) + order := orderSubmission + order.ExpiresAt = expires.UnixNano() + order.Type = types.Order_TYPE_NETWORK + svc := getTestService(t) + defer svc.ctrl.Finish() + + svc.timeSvc.EXPECT().GetTimeNow().Times(1).Return(now, nil) + err := svc.svc.PrepareSubmitOrder(context.Background(), &order) + assert.EqualError(t, err, orders.ErrUnAuthorizedOrderType.Error()) +} + func testPrepareCancelOrderSuccess(t *testing.T) { cancel := types.OrderCancellation{ OrderID: "order.Id", diff --git a/proto/api/trading.swagger.json b/proto/api/trading.swagger.json index 135241ee848..21e81d523a2 100644 --- a/proto/api/trading.swagger.json +++ b/proto/api/trading.swagger.json @@ -950,7 +950,7 @@ "STATE_ENACTED" ], "default": "STATE_UNSPECIFIED", - "description": "Proposal state transition:\nOpen -\u003e\n - Passed -\u003e Enacted.\n - Passed -\u003e Failed.\n - Declined\nRejected\nProposal can enter Failed state from any other state.\n\n - STATE_UNSPECIFIED: Default value, always invalid.\n - STATE_FAILED: Proposal could not be enacted after being accepted by the network.\n - STATE_OPEN: Proposal is open for voting.\n - STATE_PASSED: Proposal has gained enough support to be executed.\n - STATE_REJECTED: Proposal wasn't accepted (validation failed, author not allowed to submit proposals).\n - STATE_DECLINED: Proposal didn't get enough votes.\n - STATE_ENACTED: Proposal has been executed and the changes under this proposal have now been applied." + "description": "Proposal state transition:\nOpen -\u003e\n - Passed -\u003e Enacted.\n - Passed -\u003e Failed.\n - Declined\nRejected\nProposal can enter Failed state from any other state.\n\n - STATE_UNSPECIFIED: Default value, always invalid.\n - STATE_FAILED: Proposal enactment has failed - even though proposal has passed, its execusion could not be performed.\n - STATE_OPEN: Proposal is open for voting.\n - STATE_PASSED: Proposal has gained enough support to be executed.\n - STATE_REJECTED: Proposal wasn't accepted (proposal terms failed validation due to wrong configuration or failing to meet network requirements).\n - STATE_DECLINED: Proposal didn't get enough votes (either failing to gain required participation or majority level).\n - STATE_ENACTED: Proposal has been executed and the changes under this proposal have now been applied." }, "VoteValue": { "type": "string", @@ -1664,19 +1664,22 @@ "type": "object", "properties": { "proposal": { - "$ref": "#/definitions/vegaProposal" + "$ref": "#/definitions/vegaProposal", + "title": "Proposal" }, "yes": { "type": "array", "items": { "$ref": "#/definitions/vegaVote" - } + }, + "description": "All \"yes\" votes in favour of the proposal above." }, "no": { "type": "array", "items": { "$ref": "#/definitions/vegaVote" - } + }, + "description": "All \"no\" votes against the proposal above." } } }, @@ -1923,23 +1926,43 @@ "properties": { "minCloseInSeconds": { "type": "string", - "format": "int64" + "format": "int64", + "description": "Constrains minimum duration since submission (in seconds) when vote closing time is allowed to be set for a proposal." }, "maxCloseInSeconds": { "type": "string", - "format": "int64" + "format": "int64", + "description": "Constrains maximum duration since submission (in seconds) when vote closing time is allowed to be set for a proposal." }, "minEnactInSeconds": { "type": "string", - "format": "int64" + "format": "int64", + "description": "Constrains minimum duration since submission (in seconds) when enactment is allowed to be set for a proposal." }, "maxEnactInSeconds": { "type": "string", - "format": "int64" + "format": "int64", + "description": "Constrains maximum duration since submission (in seconds) when enactment is allowed to be set for a proposal." }, - "minParticipationStake": { - "type": "string", - "format": "uint64" + "requiredParticipation": { + "type": "number", + "format": "float", + "description": "Participation level required for any proposal to pass. Value from `0` to `1`." + }, + "requiredMajority": { + "type": "number", + "format": "float", + "description": "Majority level required for any proposal to pass. Value from `0.5` to `1`." + }, + "minProposerBalance": { + "type": "number", + "format": "float", + "description": "Minimum balance required for a party to be able to submit a new proposal. Value greater than `0` to `1`." + }, + "minVoterBalance": { + "type": "number", + "format": "float", + "description": "Minimum balance required for a party to be able to cast a vote. Value greater than `0` to `1`." } } }, @@ -2210,23 +2233,29 @@ "type": "object", "properties": { "ID": { - "type": "string" + "type": "string", + "description": "Proposal unique identifier." }, "reference": { - "type": "string" + "type": "string", + "description": "Proposal reference." }, "partyID": { - "type": "string" + "type": "string", + "description": "Proposal author, identifier of the party submitting the proposal." }, "state": { - "$ref": "#/definitions/ProposalState" + "$ref": "#/definitions/ProposalState", + "title": "Proposal state (see Proposal.State definition)" }, "timestamp": { "type": "string", - "format": "int64" + "format": "int64", + "description": "Proposal timestamp for date and time (in nanoseconds) when proposal was submitted to the network." }, "terms": { - "$ref": "#/definitions/vegaProposalTerms" + "$ref": "#/definitions/vegaProposalTerms", + "description": "Proposal configuration and the actual change that is meant to be executed when proposal is enacted." } } }, @@ -2236,32 +2265,32 @@ "closingTimestamp": { "type": "string", "format": "int64", - "title": "Timestamp (Unix time in seconds) when voting closes for this proposal" + "description": "Timestamp (Unix time in seconds) when voting closes for this proposal.\nConstrained by `minCloseInSeconds` and `maxCloseInSeconds` network parameters." }, "enactmentTimestamp": { "type": "string", "format": "int64", - "title": "Timestamp (Unix time in seconds) when proposal gets enacted (if passed)" - }, - "minParticipationStake": { - "type": "string", - "format": "uint64" + "description": "Timestamp (Unix time in seconds) when proposal gets enacted (if passed).\nConstrained by `minEnactInSeconds` and `maxEnactInSeconds` network parameters." }, "validationTimestamp": { "type": "string", "format": "int64" }, "updateMarket": { - "$ref": "#/definitions/vegaUpdateMarket" + "$ref": "#/definitions/vegaUpdateMarket", + "description": "Proposal change for modifying an existing market on Vega." }, "newMarket": { - "$ref": "#/definitions/vegaNewMarket" + "$ref": "#/definitions/vegaNewMarket", + "description": "Proposal change for creating new market on Vega." }, "updateNetwork": { - "$ref": "#/definitions/vegaUpdateNetwork" + "$ref": "#/definitions/vegaUpdateNetwork", + "description": "Proposal change for updating Vega network parameters." }, "newAsset": { - "$ref": "#/definitions/vegaNewAsset" + "$ref": "#/definitions/vegaNewAsset", + "description": "Proposal change for creating new assets on Vega." } } }, @@ -2586,17 +2615,21 @@ "type": "object", "properties": { "partyID": { - "type": "string" + "type": "string", + "description": "Voter's party identifier." }, "value": { - "$ref": "#/definitions/VoteValue" + "$ref": "#/definitions/VoteValue", + "description": "Actual vote." }, "proposalID": { - "type": "string" + "type": "string", + "description": "Identifier of the proposal being voted on." }, "timestamp": { "type": "string", - "format": "int64" + "format": "int64", + "description": "Vote timestamp for date and time (in nanoseconds) when vote was submitted to the network." } } } diff --git a/proto/doc/index.html b/proto/doc/index.html index 29efe0f9d75..0dd98b2a099 100644 --- a/proto/doc/index.html +++ b/proto/doc/index.html @@ -4701,21 +4701,21 @@
Proposal
All "yes" votes in favour of the proposal above.
All "no" votes against the proposal above.
Constrains minimum duration since submission (in seconds) when vote closing time is allowed to be set for a proposal.
Constrains maximum duration since submission (in seconds) when vote closing time is allowed to be set for a proposal.
Constrains minimum duration since submission (in seconds) when enactment is allowed to be set for a proposal.
Constrains maximum duration since submission (in seconds) when enactment is allowed to be set for a proposal.
Participation level required for any proposal to pass. Value from 0 to 1.
Majority level required for any proposal to pass. Value from 0.5 to 1.
Minimum balance required for a party to be able to submit a new proposal. Value greater than 0 to 1.
Minimum balance required for a party to be able to cast a vote. Value greater than 0 to 1.
Proposal unique identifier.
Proposal reference.
Proposal author, identifier of the party submitting the proposal.
Proposal state (see Proposal.State definition)
Proposal timestamp for date and time (in nanoseconds) when proposal was submitted to the network.
Proposal configuration and the actual change that is meant to be executed when proposal is enacted.
Timestamp (Unix time in seconds) when voting closes for this proposal
Timestamp (Unix time in seconds) when voting closes for this proposal. +Constrained by minCloseInSeconds and maxCloseInSeconds network parameters.
Timestamp (Unix time in seconds) when proposal gets enacted (if passed)
Timestamp (Unix time in seconds) when proposal gets enacted (if passed). +Constrained by minEnactInSeconds and maxEnactInSeconds network parameters.
TODO: this should be moved into NewAsset definition.
Proposal change for modifying an existing market on Vega.
Proposal change for creating new market on Vega.
Proposal change for updating Vega network parameters.
Proposal change for creating new assets on Vega.
Voter's party identifier.
Actual vote.
Identifier of the proposal being voted on.
Vote timestamp for date and time (in nanoseconds) when vote was submitted to the network.
Proposal could not be enacted after being accepted by the network.
Proposal enactment has failed - even though proposal has passed, its execusion could not be performed.
Proposal wasn't accepted (validation failed, author not allowed to submit proposals).
Proposal wasn't accepted (proposal terms failed validation due to wrong configuration or failing to meet network requirements).
Proposal didn't get enough votes.
Proposal didn't get enough votes (either failing to gain required participation or majority level).