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 @@

GovernanceData

proposal Proposal -

+

Proposal

yes Vote repeated -

+

All "yes" votes in favour of the proposal above.

no Vote repeated -

+

All "no" votes against the proposal above.

@@ -4739,35 +4739,56 @@

NetworkConfiguration

minCloseInSeconds int64 -

+

Constrains minimum duration since submission (in seconds) when vote closing time is allowed to be set for a proposal.

maxCloseInSeconds int64 -

+

Constrains maximum duration since submission (in seconds) when vote closing time is allowed to be set for a proposal.

minEnactInSeconds int64 -

+

Constrains minimum duration since submission (in seconds) when enactment is allowed to be set for a proposal.

maxEnactInSeconds int64 -

+

Constrains maximum duration since submission (in seconds) when enactment is allowed to be set for a proposal.

- minParticipationStake - uint64 + requiredParticipation + float -

+

Participation level required for any proposal to pass. Value from 0 to 1.

+ + + + requiredMajority + float + +

Majority level required for any proposal to pass. Value from 0.5 to 1.

+ + + + minProposerBalance + float + +

Minimum balance required for a party to be able to submit a new proposal. Value greater than 0 to 1.

+ + + + minVoterBalance + float + +

Minimum balance required for a party to be able to cast a vote. Value greater than 0 to 1.

@@ -4893,42 +4914,42 @@

Proposal

ID string -

+

Proposal unique identifier.

reference string -

+

Proposal reference.

partyID string -

+

Proposal author, identifier of the party submitting the proposal.

state Proposal.State -

+

Proposal state (see Proposal.State definition)

timestamp int64 -

+

Proposal timestamp for date and time (in nanoseconds) when proposal was submitted to the network.

terms ProposalTerms -

+

Proposal configuration and the actual change that is meant to be executed when proposal is enacted.

@@ -5001,56 +5022,51 @@

ProposalTerms

closingTimestamp int64 -

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.

enactmentTimestamp int64 -

Timestamp (Unix time in seconds) when proposal gets enacted (if passed)

- - - - minParticipationStake - uint64 - -

+

Timestamp (Unix time in seconds) when proposal gets enacted (if passed). +Constrained by minEnactInSeconds and maxEnactInSeconds network parameters.

validationTimestamp int64 -

+

TODO: this should be moved into NewAsset definition.

updateMarket UpdateMarket -

+

Proposal change for modifying an existing market on Vega.

newMarket NewMarket -

+

Proposal change for creating new market on Vega.

updateNetwork UpdateNetwork -

+

Proposal change for updating Vega network parameters.

newAsset NewAsset -

+

Proposal change for creating new assets on Vega.

@@ -5091,19 +5107,6 @@

Validated Fields

- - minParticipationStake - - - - - @@ -5183,28 +5186,28 @@

Vote

partyID string -

+

Voter's party identifier.

value Vote.Value -

+

Actual vote.

proposalID string -

+

Identifier of the proposal being voted on.

timestamp int64 -

+

Vote timestamp for date and time (in nanoseconds) when vote was submitted to the network.

@@ -5282,7 +5285,7 @@

Proposal.State

STATE_FAILED 1 -

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.

@@ -5300,13 +5303,13 @@

Proposal.State

STATE_REJECTED 4 -

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).

STATE_DECLINED 5 -

Proposal didn't get enough votes.

+

Proposal didn't get enough votes (either failing to gain required participation or majority level).

diff --git a/proto/doc/index.md b/proto/doc/index.md index 218580a240f..863bd99890a 100644 --- a/proto/doc/index.md +++ b/proto/doc/index.md @@ -1749,9 +1749,9 @@ | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| proposal | [Proposal](#vega.Proposal) | | | -| yes | [Vote](#vega.Vote) | repeated | | -| no | [Vote](#vega.Vote) | repeated | | +| proposal | [Proposal](#vega.Proposal) | | Proposal | +| yes | [Vote](#vega.Vote) | repeated | All "yes" votes in favour of the proposal above. | +| no | [Vote](#vega.Vote) | repeated | All "no" votes against the proposal above. | @@ -1766,11 +1766,14 @@ | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| minCloseInSeconds | [int64](#int64) | | | -| maxCloseInSeconds | [int64](#int64) | | | -| minEnactInSeconds | [int64](#int64) | | | -| maxEnactInSeconds | [int64](#int64) | | | -| minParticipationStake | [uint64](#uint64) | | | +| minCloseInSeconds | [int64](#int64) | | Constrains minimum duration since submission (in seconds) when vote closing time is allowed to be set for a proposal. | +| maxCloseInSeconds | [int64](#int64) | | Constrains maximum duration since submission (in seconds) when vote closing time is allowed to be set for a proposal. | +| minEnactInSeconds | [int64](#int64) | | Constrains minimum duration since submission (in seconds) when enactment is allowed to be set for a proposal. | +| maxEnactInSeconds | [int64](#int64) | | Constrains maximum duration since submission (in seconds) when enactment is allowed to be set for a proposal. | +| requiredParticipation | [float](#float) | | Participation level required for any proposal to pass. Value from `0` to `1`. | +| requiredMajority | [float](#float) | | Majority level required for any proposal to pass. Value from `0.5` to `1`. | +| minProposerBalance | [float](#float) | | Minimum balance required for a party to be able to submit a new proposal. Value greater than `0` to `1`. | +| minVoterBalance | [float](#float) | | Minimum balance required for a party to be able to cast a vote. Value greater than `0` to `1`. | @@ -1815,12 +1818,12 @@ To be implemented | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| ID | [string](#string) | | | -| reference | [string](#string) | | | -| partyID | [string](#string) | | | -| state | [Proposal.State](#vega.Proposal.State) | | | -| timestamp | [int64](#int64) | | | -| terms | [ProposalTerms](#vega.ProposalTerms) | | | +| ID | [string](#string) | | Proposal unique identifier. | +| reference | [string](#string) | | Proposal reference. | +| partyID | [string](#string) | | Proposal author, identifier of the party submitting the proposal. | +| state | [Proposal.State](#vega.Proposal.State) | | Proposal state (see Proposal.State definition) | +| timestamp | [int64](#int64) | | Proposal timestamp for date and time (in nanoseconds) when proposal was submitted to the network. | +| terms | [ProposalTerms](#vega.ProposalTerms) | | Proposal configuration and the actual change that is meant to be executed when proposal is enacted. | @@ -1835,14 +1838,13 @@ To be implemented | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| closingTimestamp | [int64](#int64) | | Timestamp (Unix time in seconds) when voting closes for this proposal | -| enactmentTimestamp | [int64](#int64) | | Timestamp (Unix time in seconds) when proposal gets enacted (if passed) | -| minParticipationStake | [uint64](#uint64) | | | -| validationTimestamp | [int64](#int64) | | | -| updateMarket | [UpdateMarket](#vega.UpdateMarket) | | | -| newMarket | [NewMarket](#vega.NewMarket) | | | -| updateNetwork | [UpdateNetwork](#vega.UpdateNetwork) | | | -| newAsset | [NewAsset](#vega.NewAsset) | | | +| closingTimestamp | [int64](#int64) | | Timestamp (Unix time in seconds) when voting closes for this proposal. Constrained by `minCloseInSeconds` and `maxCloseInSeconds` network parameters. | +| enactmentTimestamp | [int64](#int64) | | Timestamp (Unix time in seconds) when proposal gets enacted (if passed). Constrained by `minEnactInSeconds` and `maxEnactInSeconds` network parameters. | +| validationTimestamp | [int64](#int64) | | TODO: this should be moved into `NewAsset` definition. | +| updateMarket | [UpdateMarket](#vega.UpdateMarket) | | Proposal change for modifying an existing market on Vega. | +| newMarket | [NewMarket](#vega.NewMarket) | | Proposal change for creating new market on Vega. | +| updateNetwork | [UpdateNetwork](#vega.UpdateNetwork) | | Proposal change for updating Vega network parameters. | +| newAsset | [NewAsset](#vega.NewAsset) | | Proposal change for creating new assets on Vega. | @@ -1882,10 +1884,10 @@ TODO | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| partyID | [string](#string) | | | -| value | [Vote.Value](#vega.Vote.Value) | | | -| proposalID | [string](#string) | | | -| timestamp | [int64](#int64) | | | +| partyID | [string](#string) | | Voter's party identifier. | +| value | [Vote.Value](#vega.Vote.Value) | | Actual vote. | +| proposalID | [string](#string) | | Identifier of the proposal being voted on. | +| timestamp | [int64](#int64) | | Vote timestamp for date and time (in nanoseconds) when vote was submitted to the network. | @@ -1908,11 +1910,11 @@ Proposal can enter Failed state from any other state. | Name | Number | Description | | ---- | ------ | ----------- | | STATE_UNSPECIFIED | 0 | Default value, always invalid. | -| STATE_FAILED | 1 | Proposal could not be enacted after being accepted by the network. | +| STATE_FAILED | 1 | Proposal enactment has failed - even though proposal has passed, its execusion could not be performed. | | STATE_OPEN | 2 | Proposal is open for voting. | | STATE_PASSED | 3 | Proposal has gained enough support to be executed. | -| STATE_REJECTED | 4 | Proposal wasn't accepted (validation failed, author not allowed to submit proposals). | -| STATE_DECLINED | 5 | Proposal didn't get enough votes. | +| STATE_REJECTED | 4 | Proposal wasn't accepted (proposal terms failed validation due to wrong configuration or failing to meet network requirements). | +| STATE_DECLINED | 5 | Proposal didn't get enough votes (either failing to gain required participation or majority level). | | STATE_ENACTED | 6 | Proposal has been executed and the changes under this proposal have now been applied. | diff --git a/proto/governance.pb.go b/proto/governance.pb.go index 409d95717a6..a4355bde21a 100644 --- a/proto/governance.pb.go +++ b/proto/governance.pb.go @@ -33,15 +33,15 @@ type Proposal_State int32 const ( // Default value, always invalid. Proposal_STATE_UNSPECIFIED Proposal_State = 0 - // 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_STATE_FAILED Proposal_State = 1 // Proposal is open for voting. Proposal_STATE_OPEN Proposal_State = 2 // Proposal has gained enough support to be executed. Proposal_STATE_PASSED Proposal_State = 3 - // 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_STATE_REJECTED Proposal_State = 4 - // Proposal didn't get enough votes. + // Proposal didn't get enough votes (either failing to gain required participation or majority level). Proposal_STATE_DECLINED Proposal_State = 5 // Proposal has been executed and the changes under this proposal have now been applied. Proposal_STATE_ENACTED Proposal_State = 6 @@ -107,14 +107,25 @@ func (Vote_Value) EnumDescriptor() ([]byte, []int) { } type NetworkConfiguration struct { - MinCloseInSeconds int64 `protobuf:"varint,1,opt,name=minCloseInSeconds,proto3" json:"minCloseInSeconds,omitempty"` - MaxCloseInSeconds int64 `protobuf:"varint,2,opt,name=maxCloseInSeconds,proto3" json:"maxCloseInSeconds,omitempty"` - MinEnactInSeconds int64 `protobuf:"varint,3,opt,name=minEnactInSeconds,proto3" json:"minEnactInSeconds,omitempty"` - MaxEnactInSeconds int64 `protobuf:"varint,4,opt,name=maxEnactInSeconds,proto3" json:"maxEnactInSeconds,omitempty"` - MinParticipationStake uint64 `protobuf:"varint,5,opt,name=minParticipationStake,proto3" json:"minParticipationStake,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + // Constrains minimum duration since submission (in seconds) when vote closing time is allowed to be set for a proposal. + MinCloseInSeconds int64 `protobuf:"varint,1,opt,name=minCloseInSeconds,proto3" json:"minCloseInSeconds,omitempty"` + // Constrains maximum duration since submission (in seconds) when vote closing time is allowed to be set for a proposal. + MaxCloseInSeconds int64 `protobuf:"varint,2,opt,name=maxCloseInSeconds,proto3" json:"maxCloseInSeconds,omitempty"` + // Constrains minimum duration since submission (in seconds) when enactment is allowed to be set for a proposal. + MinEnactInSeconds int64 `protobuf:"varint,3,opt,name=minEnactInSeconds,proto3" json:"minEnactInSeconds,omitempty"` + // Constrains maximum duration since submission (in seconds) when enactment is allowed to be set for a proposal. + MaxEnactInSeconds int64 `protobuf:"varint,4,opt,name=maxEnactInSeconds,proto3" json:"maxEnactInSeconds,omitempty"` + // Participation level required for any proposal to pass. Value from `0` to `1`. + RequiredParticipation float32 `protobuf:"fixed32,5,opt,name=requiredParticipation,proto3" json:"requiredParticipation,omitempty"` + // Majority level required for any proposal to pass. Value from `0.5` to `1`. + RequiredMajority float32 `protobuf:"fixed32,6,opt,name=requiredMajority,proto3" json:"requiredMajority,omitempty"` + // Minimum balance required for a party to be able to submit a new proposal. Value greater than `0` to `1`. + MinProposerBalance float32 `protobuf:"fixed32,7,opt,name=minProposerBalance,proto3" json:"minProposerBalance,omitempty"` + // Minimum balance required for a party to be able to cast a vote. Value greater than `0` to `1`. + MinVoterBalance float32 `protobuf:"fixed32,8,opt,name=minVoterBalance,proto3" json:"minVoterBalance,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *NetworkConfiguration) Reset() { *m = NetworkConfiguration{} } @@ -170,9 +181,30 @@ func (m *NetworkConfiguration) GetMaxEnactInSeconds() int64 { return 0 } -func (m *NetworkConfiguration) GetMinParticipationStake() uint64 { +func (m *NetworkConfiguration) GetRequiredParticipation() float32 { + if m != nil { + return m.RequiredParticipation + } + return 0 +} + +func (m *NetworkConfiguration) GetRequiredMajority() float32 { if m != nil { - return m.MinParticipationStake + return m.RequiredMajority + } + return 0 +} + +func (m *NetworkConfiguration) GetMinProposerBalance() float32 { + if m != nil { + return m.MinProposerBalance + } + return 0 +} + +func (m *NetworkConfiguration) GetMinVoterBalance() float32 { + if m != nil { + return m.MinVoterBalance } return 0 } @@ -327,12 +359,15 @@ func (m *NewAsset) GetChanges() *AssetSource { } type ProposalTerms struct { - // 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. ClosingTimestamp int64 `protobuf:"varint,1,opt,name=closingTimestamp,proto3" json:"closingTimestamp,omitempty"` - // Timestamp (Unix time in seconds) when proposal gets enacted (if passed) - EnactmentTimestamp int64 `protobuf:"varint,2,opt,name=enactmentTimestamp,proto3" json:"enactmentTimestamp,omitempty"` - MinParticipationStake uint64 `protobuf:"varint,3,opt,name=minParticipationStake,proto3" json:"minParticipationStake,omitempty"` - ValidationTimestamp int64 `protobuf:"varint,4,opt,name=validationTimestamp,proto3" json:"validationTimestamp,omitempty"` + // Timestamp (Unix time in seconds) when proposal gets enacted (if passed). + // Constrained by `minEnactInSeconds` and `maxEnactInSeconds` network parameters. + EnactmentTimestamp int64 `protobuf:"varint,2,opt,name=enactmentTimestamp,proto3" json:"enactmentTimestamp,omitempty"` + ValidationTimestamp int64 `protobuf:"varint,5,opt,name=validationTimestamp,proto3" json:"validationTimestamp,omitempty"` + // Actual changes being proposed + // // Types that are valid to be assigned to Change: // *ProposalTerms_UpdateMarket // *ProposalTerms_NewMarket @@ -383,13 +418,6 @@ func (m *ProposalTerms) GetEnactmentTimestamp() int64 { return 0 } -func (m *ProposalTerms) GetMinParticipationStake() uint64 { - if m != nil { - return m.MinParticipationStake - } - return 0 -} - func (m *ProposalTerms) GetValidationTimestamp() int64 { if m != nil { return m.ValidationTimestamp @@ -471,12 +499,15 @@ func (*ProposalTerms) XXX_OneofWrappers() []interface{} { } type GovernanceData struct { - Proposal *Proposal `protobuf:"bytes,1,opt,name=proposal,proto3" json:"proposal,omitempty"` - Yes []*Vote `protobuf:"bytes,2,rep,name=yes,proto3" json:"yes,omitempty"` - No []*Vote `protobuf:"bytes,3,rep,name=no,proto3" json:"no,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + // Proposal + Proposal *Proposal `protobuf:"bytes,1,opt,name=proposal,proto3" json:"proposal,omitempty"` + // All "yes" votes in favour of the proposal above. + Yes []*Vote `protobuf:"bytes,2,rep,name=yes,proto3" json:"yes,omitempty"` + // All "no" votes against the proposal above. + No []*Vote `protobuf:"bytes,3,rep,name=no,proto3" json:"no,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *GovernanceData) Reset() { *m = GovernanceData{} } @@ -526,11 +557,17 @@ func (m *GovernanceData) GetNo() []*Vote { } type Proposal struct { - ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"` - Reference string `protobuf:"bytes,2,opt,name=reference,proto3" json:"reference,omitempty"` - PartyID string `protobuf:"bytes,3,opt,name=partyID,proto3" json:"partyID,omitempty"` - State Proposal_State `protobuf:"varint,4,opt,name=state,proto3,enum=vega.Proposal_State" json:"state,omitempty"` - Timestamp int64 `protobuf:"varint,5,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + // Proposal unique identifier. + ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"` + // Proposal reference. + Reference string `protobuf:"bytes,2,opt,name=reference,proto3" json:"reference,omitempty"` + // Proposal author, identifier of the party submitting the proposal. + PartyID string `protobuf:"bytes,3,opt,name=partyID,proto3" json:"partyID,omitempty"` + // Proposal state (see Proposal.State definition) + State Proposal_State `protobuf:"varint,4,opt,name=state,proto3,enum=vega.Proposal_State" json:"state,omitempty"` + // Proposal timestamp for date and time (in nanoseconds) when proposal was submitted to the network. + Timestamp int64 `protobuf:"varint,5,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + // Proposal configuration and the actual change that is meant to be executed when proposal is enacted. Terms *ProposalTerms `protobuf:"bytes,6,opt,name=terms,proto3" json:"terms,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -605,13 +642,17 @@ func (m *Proposal) GetTerms() *ProposalTerms { } type Vote struct { - PartyID string `protobuf:"bytes,1,opt,name=partyID,proto3" json:"partyID,omitempty"` - Value Vote_Value `protobuf:"varint,2,opt,name=value,proto3,enum=vega.Vote_Value" json:"value,omitempty"` - ProposalID string `protobuf:"bytes,3,opt,name=proposalID,proto3" json:"proposalID,omitempty"` - Timestamp int64 `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + // Voter's party identifier. + PartyID string `protobuf:"bytes,1,opt,name=partyID,proto3" json:"partyID,omitempty"` + // Actual vote. + Value Vote_Value `protobuf:"varint,2,opt,name=value,proto3,enum=vega.Vote_Value" json:"value,omitempty"` + // Identifier of the proposal being voted on. + ProposalID string `protobuf:"bytes,3,opt,name=proposalID,proto3" json:"proposalID,omitempty"` + // Vote timestamp for date and time (in nanoseconds) when vote was submitted to the network. + Timestamp int64 `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *Vote) Reset() { *m = Vote{} } @@ -684,59 +725,60 @@ func init() { func init() { proto.RegisterFile("proto/governance.proto", fileDescriptor_c891e73c7d2524a3) } var fileDescriptor_c891e73c7d2524a3 = []byte{ - // 851 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x55, 0xdd, 0x6e, 0xe2, 0x46, - 0x18, 0xc5, 0xe6, 0x27, 0xf0, 0x2d, 0x50, 0xe7, 0xcb, 0x6e, 0x65, 0x45, 0x2b, 0x25, 0xf5, 0x45, - 0x15, 0x55, 0xbb, 0xd0, 0x92, 0x6a, 0x55, 0x29, 0x55, 0x2b, 0xc0, 0xde, 0x86, 0x2a, 0xcb, 0x22, - 0x9b, 0x44, 0x6d, 0x6f, 0xaa, 0x59, 0x67, 0x42, 0xac, 0xe0, 0x19, 0x64, 0x0f, 0xd0, 0xbd, 0xef, - 0x45, 0x6f, 0xfa, 0x68, 0x7d, 0x83, 0x4a, 0x91, 0xf2, 0x04, 0x7d, 0x84, 0xca, 0x33, 0xc6, 0xe6, - 0x6f, 0xaf, 0x12, 0x9f, 0x73, 0xbe, 0x33, 0xe6, 0x9c, 0x6f, 0x00, 0x3e, 0x9f, 0x45, 0x5c, 0xf0, - 0xf6, 0x84, 0x2f, 0x68, 0xc4, 0x08, 0xf3, 0x69, 0x4b, 0x02, 0x58, 0x5a, 0xd0, 0x09, 0x39, 0x7e, - 0x33, 0x09, 0xc4, 0xfd, 0xfc, 0x43, 0xcb, 0xe7, 0x61, 0x3b, 0x5c, 0x06, 0xe2, 0x81, 0x2f, 0xdb, - 0x13, 0xfe, 0x5a, 0x4a, 0x5e, 0x2f, 0xc8, 0x34, 0xb8, 0x25, 0x82, 0x47, 0x71, 0x3b, 0xfb, 0x57, - 0x4d, 0x1f, 0x1f, 0x29, 0xd7, 0x90, 0x44, 0x0f, 0x54, 0xc4, 0x29, 0x88, 0x0a, 0x24, 0x71, 0x9c, - 0x61, 0xd6, 0x9f, 0x3a, 0x3c, 0x1f, 0x52, 0xb1, 0xe4, 0xd1, 0x43, 0x9f, 0xb3, 0xbb, 0x60, 0x32, - 0x8f, 0x88, 0x08, 0x38, 0xc3, 0x57, 0x70, 0x18, 0x06, 0xac, 0x3f, 0xe5, 0x31, 0x1d, 0x30, 0x8f, - 0xfa, 0x9c, 0xdd, 0xc6, 0xa6, 0x76, 0xaa, 0x9d, 0x15, 0xdd, 0x5d, 0x42, 0xaa, 0xc9, 0x1f, 0x5b, - 0x6a, 0x3d, 0x55, 0x6f, 0x13, 0xa9, 0xb7, 0xc3, 0x88, 0x2f, 0x72, 0x75, 0x31, 0xf3, 0xde, 0x24, - 0x52, 0xef, 0x2d, 0x75, 0x29, 0xf3, 0xde, 0x52, 0x7f, 0x0b, 0x2f, 0xc2, 0x80, 0x8d, 0x48, 0x24, - 0x02, 0x3f, 0x98, 0xc9, 0xcf, 0xe2, 0x09, 0xf2, 0x40, 0xcd, 0xf2, 0xa9, 0x76, 0x56, 0x72, 0xf7, - 0x93, 0x56, 0x13, 0xea, 0xd7, 0xb3, 0x5b, 0x22, 0xe8, 0x3b, 0x99, 0x98, 0x75, 0x01, 0xb5, 0x21, - 0x5d, 0xaa, 0x07, 0x6c, 0xc1, 0x81, 0x7f, 0x4f, 0xd8, 0x84, 0xaa, 0x00, 0x9e, 0x75, 0xea, 0xad, - 0xa4, 0x9c, 0x96, 0xa2, 0x7b, 0x95, 0xa7, 0xc7, 0x13, 0xfd, 0x54, 0x73, 0x57, 0x22, 0xeb, 0x1d, - 0x34, 0x94, 0x59, 0x1a, 0x2c, 0x7e, 0xbf, 0x6d, 0x70, 0xac, 0x0c, 0xf6, 0x05, 0xbf, 0x6b, 0xf7, - 0x23, 0x54, 0x87, 0x74, 0xd9, 0x4d, 0x5a, 0xc3, 0xf3, 0x6d, 0xa7, 0x43, 0xe5, 0x24, 0x59, 0x8f, - 0xcf, 0x23, 0x9f, 0xee, 0x1a, 0xfc, 0x53, 0x84, 0xc6, 0x28, 0xe2, 0x33, 0x1e, 0x93, 0xe9, 0x98, - 0x46, 0x61, 0x8c, 0x1d, 0x30, 0xfc, 0x29, 0x8f, 0x03, 0x36, 0x19, 0x07, 0x21, 0x8d, 0x05, 0x09, - 0x67, 0xaa, 0x5b, 0x35, 0x6c, 0x14, 0xdc, 0x1d, 0x1e, 0xdf, 0x00, 0xd2, 0x24, 0xea, 0x90, 0x32, - 0x91, 0x4f, 0xe9, 0x1b, 0x53, 0x7b, 0x14, 0xf8, 0xc3, 0xa7, 0x0a, 0x49, 0x0a, 0x2f, 0xf5, 0xaa, - 0x4f, 0x8f, 0x27, 0x25, 0xa3, 0x60, 0xd2, 0x4f, 0x54, 0x83, 0x5f, 0xc3, 0x51, 0xba, 0xdd, 0x01, - 0x67, 0xf9, 0xc1, 0x6a, 0x01, 0xf6, 0x51, 0xf8, 0x1d, 0xd4, 0xe7, 0x6b, 0x65, 0x9a, 0x54, 0x26, - 0x85, 0x2a, 0xa9, 0xf5, 0x9a, 0x2f, 0x0b, 0xee, 0x86, 0x12, 0xdb, 0x50, 0x63, 0xab, 0xda, 0xcd, - 0x3b, 0x39, 0xf6, 0xd9, 0xaa, 0xaa, 0x65, 0x36, 0x93, 0x6b, 0xf0, 0x02, 0x1a, 0xf3, 0xf5, 0xaa, - 0xcd, 0x89, 0x1c, 0x3a, 0x5a, 0x3f, 0x2b, 0xa5, 0x2e, 0x0b, 0xee, 0xa6, 0x16, 0x5f, 0x41, 0x95, - 0xa5, 0xc5, 0x9a, 0xf7, 0x72, 0xae, 0x99, 0x1d, 0x26, 0xd1, 0xcb, 0x82, 0x9b, 0x29, 0x7a, 0x55, - 0xa8, 0xa8, 0x42, 0xad, 0x05, 0x34, 0x7f, 0xca, 0xbe, 0x2e, 0x6c, 0x22, 0x08, 0x7e, 0x05, 0xd5, - 0x59, 0x5a, 0x70, 0xba, 0x17, 0xa9, 0xd3, 0xaa, 0x76, 0x37, 0xe3, 0xf1, 0x25, 0x14, 0x3f, 0xd2, - 0xe4, 0x72, 0x16, 0xcf, 0x9e, 0x75, 0x40, 0xc9, 0x6e, 0xb8, 0xa0, 0x6e, 0x02, 0xe3, 0x31, 0xe8, - 0x8c, 0x9b, 0xc5, 0x1d, 0x52, 0x67, 0xdc, 0xfa, 0x4f, 0x87, 0xea, 0xca, 0x10, 0x9b, 0xa0, 0x0f, - 0x6c, 0x79, 0x58, 0xcd, 0xd5, 0x07, 0x36, 0xbe, 0x84, 0x5a, 0x44, 0xef, 0x68, 0x44, 0x99, 0x4f, - 0xe5, 0x56, 0xd4, 0xdc, 0x1c, 0xc0, 0x53, 0x38, 0x98, 0x91, 0x48, 0x7c, 0x1c, 0xd8, 0xb2, 0xf6, - 0x9a, 0xda, 0x98, 0x5f, 0x34, 0x77, 0x05, 0xe3, 0x39, 0x94, 0x63, 0x41, 0x04, 0x95, 0xc5, 0x36, - 0x3b, 0xcf, 0x37, 0xdf, 0xbf, 0xe5, 0x25, 0x5c, 0xef, 0xe0, 0xe9, 0xf1, 0xa4, 0xf8, 0x97, 0xa6, - 0xb9, 0x4a, 0x9b, 0x1c, 0x2a, 0xb2, 0x8d, 0x28, 0xcb, 0x8d, 0xc8, 0x01, 0xfc, 0x06, 0xca, 0x22, - 0x59, 0x77, 0xb3, 0xb2, 0x5e, 0xca, 0xc6, 0x4d, 0xc8, 0x2e, 0x8b, 0x52, 0x5a, 0x7f, 0x6b, 0x50, - 0x96, 0x47, 0xe1, 0x0b, 0x38, 0xf4, 0xc6, 0xdd, 0xb1, 0xf3, 0xfb, 0xf5, 0xd0, 0x1b, 0x39, 0xfd, - 0xc1, 0xdb, 0x81, 0x63, 0x1b, 0x05, 0x34, 0xa0, 0xae, 0xe0, 0xb7, 0xdd, 0xc1, 0x95, 0x63, 0x1b, - 0x1a, 0x36, 0x01, 0x14, 0xf2, 0x7e, 0xe4, 0x0c, 0x0d, 0x3d, 0x57, 0x8c, 0xba, 0x9e, 0xe7, 0xd8, - 0x46, 0x11, 0x11, 0x9a, 0x0a, 0x71, 0x9d, 0x9f, 0x9d, 0xfe, 0xd8, 0xb1, 0x8d, 0x52, 0x8e, 0xd9, - 0x4e, 0xff, 0x6a, 0x30, 0x74, 0x6c, 0xa3, 0x8c, 0x87, 0xd0, 0x50, 0x98, 0x33, 0xec, 0x4a, 0x59, - 0xc5, 0xfa, 0x57, 0x83, 0x52, 0x92, 0xff, 0x7a, 0x80, 0xda, 0xfe, 0x00, 0xdb, 0x50, 0x5e, 0x90, - 0xe9, 0x5c, 0x85, 0xdf, 0xec, 0x18, 0x79, 0x79, 0xad, 0x9b, 0x04, 0x5f, 0x0b, 0x4f, 0xea, 0xf0, - 0x4b, 0x80, 0xd5, 0x52, 0xec, 0xd4, 0xb2, 0xc6, 0x6c, 0x86, 0x5c, 0xda, 0x0a, 0xd9, 0xba, 0x80, - 0xb2, 0xb4, 0x4f, 0x02, 0xbb, 0xe9, 0x5e, 0x5d, 0x6f, 0x07, 0x56, 0x87, 0xaa, 0x82, 0x87, 0xef, - 0x0d, 0x0d, 0x1b, 0x50, 0x53, 0x4f, 0xbf, 0x3a, 0x9e, 0xa1, 0xf7, 0xbe, 0xf8, 0xed, 0xc4, 0xe7, - 0xb7, 0x54, 0xbe, 0xaa, 0xfc, 0x3d, 0xf2, 0xf9, 0xb4, 0x15, 0xf0, 0x76, 0xf2, 0xdc, 0x96, 0xc0, - 0x87, 0x8a, 0xfc, 0x73, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x61, 0xef, 0x6c, 0x66, 0x28, - 0x07, 0x00, 0x00, + // 875 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x55, 0xed, 0x6e, 0xe2, 0x46, + 0x14, 0xc5, 0xe6, 0x23, 0x70, 0x17, 0x58, 0xe7, 0x66, 0xb7, 0x42, 0xd1, 0x4a, 0x49, 0xf9, 0x51, + 0x45, 0xab, 0x5d, 0xd3, 0x92, 0x6a, 0x55, 0x29, 0x95, 0x2a, 0xc0, 0xde, 0x86, 0x2a, 0x61, 0x91, + 0x21, 0x51, 0xdb, 0x3f, 0xd5, 0xac, 0x99, 0x10, 0x37, 0x78, 0x86, 0xda, 0x03, 0x34, 0x6f, 0x50, + 0x55, 0xda, 0x37, 0xac, 0xb4, 0x52, 0x9e, 0xa0, 0x8f, 0xb0, 0xf2, 0x8c, 0xb1, 0xc1, 0xf0, 0x2b, + 0x99, 0x73, 0xce, 0x3d, 0xe3, 0xb9, 0xe7, 0xce, 0x00, 0x5f, 0xcd, 0x03, 0x2e, 0x78, 0x6b, 0xca, + 0x97, 0x34, 0x60, 0x84, 0xb9, 0xd4, 0x94, 0x00, 0x16, 0x96, 0x74, 0x4a, 0x8e, 0xdf, 0x4d, 0x3d, + 0x71, 0xbf, 0xf8, 0x68, 0xba, 0xdc, 0x6f, 0xf9, 0x2b, 0x4f, 0x3c, 0xf0, 0x55, 0x6b, 0xca, 0xdf, + 0x4a, 0xc9, 0xdb, 0x25, 0x99, 0x79, 0x13, 0x22, 0x78, 0x10, 0xb6, 0x92, 0x7f, 0x55, 0xf5, 0xf1, + 0x91, 0x72, 0xf5, 0x49, 0xf0, 0x40, 0x45, 0x18, 0x83, 0xa8, 0x40, 0x12, 0x86, 0x09, 0xd6, 0xfc, + 0x37, 0x0f, 0x2f, 0x06, 0x54, 0xac, 0x78, 0xf0, 0xd0, 0xe3, 0xec, 0xce, 0x9b, 0x2e, 0x02, 0x22, + 0x3c, 0xce, 0xf0, 0x0d, 0x1c, 0xfa, 0x1e, 0xeb, 0xcd, 0x78, 0x48, 0xfb, 0x6c, 0x44, 0x5d, 0xce, + 0x26, 0x61, 0x43, 0x3b, 0xd5, 0xce, 0xf2, 0xce, 0x2e, 0x21, 0xd5, 0xe4, 0xef, 0x8c, 0x5a, 0x8f, + 0xd5, 0x59, 0x22, 0xf6, 0xb6, 0x19, 0x71, 0x45, 0xaa, 0xce, 0x27, 0xde, 0xdb, 0x44, 0xec, 0x9d, + 0x51, 0x17, 0x12, 0xef, 0x8c, 0xfa, 0x7b, 0x78, 0x19, 0xd0, 0xbf, 0x16, 0x5e, 0x40, 0x27, 0x43, + 0x12, 0x08, 0xcf, 0xf5, 0xe6, 0xf2, 0x40, 0x8d, 0xe2, 0xa9, 0x76, 0xa6, 0x3b, 0xfb, 0x49, 0x7c, + 0x0d, 0xc6, 0x9a, 0xb8, 0x26, 0x7f, 0xf2, 0xc0, 0x13, 0x8f, 0x8d, 0x92, 0x2c, 0xd8, 0xc1, 0xd1, + 0x04, 0xf4, 0x3d, 0x36, 0x0c, 0xf8, 0x9c, 0x87, 0x34, 0xe8, 0x92, 0x59, 0x94, 0x5a, 0xe3, 0x40, + 0xaa, 0xf7, 0x30, 0x78, 0x06, 0xcf, 0x7d, 0x8f, 0xdd, 0x72, 0x91, 0x8a, 0xcb, 0x52, 0x9c, 0x85, + 0x9b, 0x75, 0xa8, 0xde, 0xcc, 0x27, 0x44, 0xd0, 0x6b, 0x99, 0x5b, 0xf3, 0x02, 0x2a, 0x03, 0xba, + 0x52, 0x0b, 0x34, 0xe1, 0xc0, 0xbd, 0x27, 0x6c, 0x4a, 0x55, 0x0c, 0xcf, 0xda, 0x55, 0x33, 0x1a, + 0x11, 0x53, 0xd1, 0xdd, 0xd2, 0xd3, 0xe7, 0x13, 0xfd, 0x54, 0x73, 0xd6, 0xa2, 0xe6, 0x35, 0xd4, + 0x94, 0x59, 0x1c, 0x2f, 0xfe, 0x98, 0x35, 0x38, 0x56, 0x06, 0xfb, 0xe2, 0xdf, 0xb5, 0xfb, 0x09, + 0xca, 0x03, 0xba, 0xea, 0x44, 0xb3, 0x83, 0xe7, 0x59, 0xa7, 0x43, 0xe5, 0x24, 0xd9, 0x11, 0x5f, + 0x04, 0x2e, 0xdd, 0x35, 0xf8, 0x94, 0x87, 0x9a, 0x6a, 0x0d, 0x99, 0x8d, 0x69, 0xe0, 0x87, 0xd8, + 0x06, 0xc3, 0x9d, 0xf1, 0xd0, 0x63, 0xd3, 0xb1, 0xe7, 0xd3, 0x50, 0x10, 0x7f, 0xae, 0x26, 0x4c, + 0x15, 0x1b, 0x39, 0x67, 0x87, 0xc7, 0x77, 0x80, 0x34, 0x0a, 0xdc, 0xa7, 0x4c, 0xa4, 0x55, 0xfa, + 0x56, 0xd5, 0x1e, 0x05, 0x7e, 0x0b, 0x47, 0xf1, 0x1d, 0xf1, 0x38, 0x4b, 0x0b, 0x8b, 0x72, 0x8c, + 0xf6, 0x51, 0xf8, 0x03, 0x54, 0x17, 0x1b, 0x61, 0x34, 0xa8, 0x3c, 0x29, 0xaa, 0x93, 0x6e, 0xc6, + 0x74, 0x99, 0x73, 0xb6, 0x94, 0xd8, 0x82, 0x0a, 0x5b, 0xc7, 0xd6, 0xb8, 0x93, 0x65, 0xcf, 0xd7, + 0xad, 0x5e, 0x25, 0x35, 0xa9, 0x06, 0x2f, 0xa0, 0xb6, 0xd8, 0x8c, 0xaa, 0x31, 0x95, 0x45, 0x47, + 0x9b, 0x7b, 0xc5, 0xd4, 0x65, 0xce, 0xd9, 0xd6, 0xe2, 0x1b, 0x28, 0xb3, 0x38, 0x98, 0xc6, 0xbd, + 0xac, 0xab, 0x27, 0x9b, 0x49, 0xf4, 0x32, 0xe7, 0x24, 0x8a, 0x6e, 0x19, 0x4a, 0x2a, 0x90, 0xe6, + 0x12, 0xea, 0x3f, 0x27, 0x8f, 0x8e, 0x45, 0x04, 0xc1, 0xd7, 0x50, 0x9e, 0xc7, 0x01, 0xc5, 0xb9, + 0xc6, 0x4e, 0xeb, 0xd8, 0x9c, 0x84, 0xc7, 0x57, 0x90, 0x7f, 0xa4, 0xd1, 0x15, 0xcf, 0x9f, 0x3d, + 0x6b, 0x83, 0x92, 0x45, 0xb3, 0xec, 0x44, 0x30, 0x1e, 0x83, 0xce, 0x78, 0x23, 0xbf, 0x43, 0xea, + 0x8c, 0x37, 0xff, 0xd7, 0xa1, 0xbc, 0x36, 0xc4, 0x3a, 0xe8, 0x7d, 0x4b, 0x6e, 0x56, 0x71, 0xf4, + 0xbe, 0x85, 0xaf, 0xa0, 0x12, 0xd0, 0x3b, 0x1a, 0xd0, 0xe8, 0x96, 0xe8, 0x12, 0x4e, 0x01, 0x3c, + 0x85, 0x83, 0x39, 0x09, 0xc4, 0x63, 0xdf, 0x92, 0xaf, 0x45, 0x45, 0x25, 0xfe, 0xab, 0xe6, 0xac, + 0x61, 0x3c, 0x87, 0x62, 0x28, 0x88, 0xa0, 0xf2, 0x7d, 0xa8, 0xb7, 0x5f, 0x6c, 0x7f, 0xbf, 0x39, + 0x8a, 0xb8, 0xee, 0xc1, 0xd3, 0xe7, 0x93, 0xfc, 0x3f, 0x9a, 0xe6, 0x28, 0x6d, 0xb4, 0xa9, 0xc8, + 0x4c, 0x44, 0x0a, 0xe0, 0x77, 0x50, 0x14, 0xd1, 0xb8, 0xca, 0xf7, 0x20, 0x09, 0x65, 0x6b, 0x92, + 0x93, 0x61, 0x57, 0xca, 0xe6, 0x27, 0x0d, 0x8a, 0x72, 0x2b, 0x7c, 0x09, 0x87, 0xa3, 0x71, 0x67, + 0x6c, 0xff, 0x71, 0x33, 0x18, 0x0d, 0xed, 0x5e, 0xff, 0x7d, 0xdf, 0xb6, 0x8c, 0x1c, 0x1a, 0x50, + 0x55, 0xf0, 0xfb, 0x4e, 0xff, 0xca, 0xb6, 0x0c, 0x0d, 0xeb, 0x00, 0x0a, 0xf9, 0x30, 0xb4, 0x07, + 0x86, 0x9e, 0x2a, 0x86, 0x9d, 0xd1, 0xc8, 0xb6, 0x8c, 0x3c, 0x22, 0xd4, 0x15, 0xe2, 0xd8, 0xbf, + 0xd8, 0xbd, 0xb1, 0x6d, 0x19, 0x85, 0x14, 0xb3, 0xec, 0xde, 0x55, 0x7f, 0x60, 0x5b, 0x46, 0x11, + 0x0f, 0xa1, 0xa6, 0x30, 0x7b, 0xd0, 0x91, 0xb2, 0x52, 0xf3, 0x3f, 0x0d, 0x0a, 0x51, 0xff, 0x37, + 0x1b, 0xa8, 0xed, 0x6f, 0x60, 0x0b, 0x8a, 0x4b, 0x32, 0x5b, 0xa8, 0xe6, 0xd7, 0xdb, 0x46, 0x1a, + 0x9e, 0x79, 0x1b, 0xe1, 0x1b, 0xcd, 0x93, 0x3a, 0xfc, 0x06, 0x60, 0x3d, 0x14, 0x3b, 0xb1, 0x6c, + 0x30, 0xdb, 0x4d, 0x2e, 0x64, 0x9a, 0xdc, 0xbc, 0x80, 0xa2, 0xb4, 0x8f, 0x1a, 0x76, 0xdb, 0xb9, + 0xba, 0xc9, 0x36, 0xac, 0x0a, 0x65, 0x05, 0x0f, 0x3e, 0x18, 0x1a, 0xd6, 0xa0, 0xa2, 0x56, 0xbf, + 0xd9, 0x23, 0x43, 0xef, 0x7e, 0xfd, 0xfb, 0x89, 0xcb, 0x27, 0x54, 0x7e, 0xaa, 0xfc, 0x55, 0x73, + 0xf9, 0xcc, 0xf4, 0x78, 0x2b, 0x5a, 0xb7, 0x24, 0xf0, 0xb1, 0x24, 0xff, 0x9c, 0x7f, 0x09, 0x00, + 0x00, 0xff, 0xff, 0x3e, 0xe0, 0x04, 0xf6, 0x6e, 0x07, 0x00, 0x00, } diff --git a/proto/governance.proto b/proto/governance.proto index 3d256d58ebc..542c4b23a9c 100644 --- a/proto/governance.proto +++ b/proto/governance.proto @@ -9,13 +9,24 @@ import "proto/markets.proto"; import "proto/assets.proto"; message NetworkConfiguration { + // Constrains minimum duration since submission (in seconds) when vote closing time is allowed to be set for a proposal. int64 minCloseInSeconds = 1; + // Constrains maximum duration since submission (in seconds) when vote closing time is allowed to be set for a proposal. int64 maxCloseInSeconds = 2; - int64 minEnactInSeconds = 3; - int64 maxEnactInSeconds = 4; - - uint64 minParticipationStake = 5; + // Constrains minimum duration since submission (in seconds) when enactment is allowed to be set for a proposal. + int64 minEnactInSeconds = 3; + // Constrains maximum duration since submission (in seconds) when enactment is allowed to be set for a proposal. + int64 maxEnactInSeconds = 4; + + // Participation level required for any proposal to pass. Value from `0` to `1`. + float requiredParticipation = 5; + // Majority level required for any proposal to pass. Value from `0.5` to `1`. + float requiredMajority = 6; + // Minimum balance required for a party to be able to submit a new proposal. Value greater than `0` to `1`. + float minProposerBalance = 7; + // Minimum balance required for a party to be able to cast a vote. Value greater than `0` to `1`. + float minVoterBalance = 8; } message UpdateMarket { @@ -34,23 +45,34 @@ message NewAsset { } message ProposalTerms { - // Timestamp (Unix time in seconds) when voting closes for this proposal - int64 closingTimestamp = 1 [(validator.field) = {int_gt: 0}]; - // Timestamp (Unix time in seconds) when proposal gets enacted (if passed) - int64 enactmentTimestamp = 2 [(validator.field) = {int_gt: 0}]; - uint64 minParticipationStake = 3 [(validator.field) = {int_gt: 0, int_lt: 101}]; - int64 validationTimestamp = 4; + // Timestamp (Unix time in seconds) when voting closes for this proposal. + // Constrained by `minCloseInSeconds` and `maxCloseInSeconds` network parameters. + int64 closingTimestamp = 1 [(validator.field) = {int_gt: 0}]; + // Timestamp (Unix time in seconds) when proposal gets enacted (if passed). + // Constrained by `minEnactInSeconds` and `maxEnactInSeconds` network parameters. + int64 enactmentTimestamp = 2 [(validator.field) = {int_gt: 0}]; + + int64 validationTimestamp = 5; //TODO: this should be moved into `NewAsset` definition. + + // Actual changes being proposed oneof change { + // Proposal change for modifying an existing market on Vega. UpdateMarket updateMarket = 101; + // Proposal change for creating new market on Vega. NewMarket newMarket = 102; + // Proposal change for updating Vega network parameters. UpdateNetwork updateNetwork = 103; + // Proposal change for creating new assets on Vega. NewAsset newAsset = 104; }; } message GovernanceData { + // Proposal Proposal proposal = 1; + // All "yes" votes in favour of the proposal above. repeated Vote yes = 2; + // All "no" votes against the proposal above. repeated Vote no = 3; } @@ -66,7 +88,7 @@ message Proposal { // Default value, always invalid. STATE_UNSPECIFIED = 0; - // 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. STATE_FAILED = 1; // Proposal is open for voting. @@ -75,21 +97,31 @@ message Proposal { // Proposal has gained enough support to be executed. STATE_PASSED = 3; - // 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). STATE_REJECTED = 4; - // Proposal didn't get enough votes. + // Proposal didn't get enough votes (either failing to gain required participation or majority level). STATE_DECLINED = 5; // Proposal has been executed and the changes under this proposal have now been applied. STATE_ENACTED = 6; + + // Note: If adding an enum value, add a matching entry in: + // - gateway/graphql/helpers_enum.go + // - gateway/graphql/schema.graphql (enum ProposalState) } + // Proposal unique identifier. string ID = 1; + // Proposal reference. string reference = 2; + // Proposal author, identifier of the party submitting the proposal. string partyID = 3 [(validator.field) = {string_not_empty : true}]; + // Proposal state (see Proposal.State definition) State state = 4 [(validator.field) = {is_in_enum: true}]; + // Proposal timestamp for date and time (in nanoseconds) when proposal was submitted to the network. int64 timestamp = 5; + // Proposal configuration and the actual change that is meant to be executed when proposal is enacted. ProposalTerms terms = 6 [(validator.field) = {msg_exists: true}]; } @@ -104,10 +136,18 @@ message Vote { // A vote in favour of the proposal. VALUE_YES = 2; + + // Note: If adding an enum value, add a matching entry in: + // - gateway/graphql/helpers_enum.go + // - gateway/graphql/schema.graphql (enum VoteValue) } + // Voter's party identifier. string partyID = 1 [(validator.field) = {string_not_empty : true}]; + // Actual vote. Value value = 2 [(validator.field) = {is_in_enum : true}]; + // Identifier of the proposal being voted on. string proposalID = 3 [(validator.field) = {string_not_empty : true}]; + // Vote timestamp for date and time (in nanoseconds) when vote was submitted to the network. int64 timestamp = 4; } diff --git a/proto/governance.validator.pb.go b/proto/governance.validator.pb.go index 5033dd5ee1d..81cd0e1851a 100644 --- a/proto/governance.validator.pb.go +++ b/proto/governance.validator.pb.go @@ -63,12 +63,6 @@ func (this *ProposalTerms) Validate() error { if !(this.EnactmentTimestamp > 0) { return github_com_mwitkow_go_proto_validators.FieldError("EnactmentTimestamp", fmt.Errorf(`value '%v' must be greater than '0'`, this.EnactmentTimestamp)) } - if !(this.MinParticipationStake > 0) { - return github_com_mwitkow_go_proto_validators.FieldError("MinParticipationStake", fmt.Errorf(`value '%v' must be greater than '0'`, this.MinParticipationStake)) - } - if !(this.MinParticipationStake < 101) { - return github_com_mwitkow_go_proto_validators.FieldError("MinParticipationStake", fmt.Errorf(`value '%v' must be less than '101'`, this.MinParticipationStake)) - } if oneOfNester, ok := this.GetChange().(*ProposalTerms_UpdateMarket); ok { if oneOfNester.UpdateMarket != nil { if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(oneOfNester.UpdateMarket); err != nil { diff --git a/proto/vega.proto b/proto/vega.proto index 32987e3b1f0..b44166a605b 100644 --- a/proto/vega.proto +++ b/proto/vega.proto @@ -14,6 +14,10 @@ enum Side { // Sell SIDE_SELL = 2; + + // Note: If adding an enum value, add a matching entry in: + // - gateway/graphql/helpers_enum.go + // - gateway/graphql/schema.graphql (enum Interval) } enum Interval { @@ -38,6 +42,10 @@ enum Interval { // 1 day INTERVAL_I1D = 86400; + + // Note: If adding an enum value, add a matching entry in: + // - gateway/graphql/helpers_enum.go + // - gateway/graphql/schema.graphql (enum Interval) } message Price { @@ -91,6 +99,10 @@ message Order { // fill or kill TIF_FOK = 4; + + // Note: If adding an enum value, add a matching entry in: + // - gateway/graphql/helpers_enum.go + // - gateway/graphql/schema.graphql (enum OrderTimeInForce) } // Order Type @@ -106,6 +118,10 @@ message Order { // used for orders where the initiating party is the network (used for distressed traders) TYPE_NETWORK = 3; + + // Note: If adding an enum value, add a matching entry in: + // - gateway/graphql/helpers_enum.go + // - gateway/graphql/schema.graphql (enum OrderType) } enum Status { @@ -117,6 +133,10 @@ message Order { STATUS_FILLED = 5; STATUS_REJECTED = 6; STATUS_PARTIALLY_FILLED = 7; + + // Note: If adding an enum value, add a matching entry in: + // - gateway/graphql/helpers_enum.go + // - gateway/graphql/schema.graphql (enum OrderStatus) } string id = 1; @@ -175,7 +195,10 @@ enum OrderError { ORDER_ERROR_INVALID_PERSISTENCE = 18; ORDER_ERROR_INVALID_TYPE = 19; - // Note: If adding an enum value, add a matching entry in proto/errors.go. + // Note: If adding an enum value, add a matching entry in: + // - proto/errors.go (func Error) + // - gateway/graphql/helpers_enum.go + // - gateway/graphql/schema.graphql (enum RejectionReason) } message Trade { @@ -187,6 +210,10 @@ message Trade { TYPE_DEFAULT = 1; TYPE_NETWORK_CLOSE_OUT_GOOD = 2; TYPE_NETWORK_CLOSE_OUT_BAD = 3; + + // Note: If adding an enum value, add a matching entry in: + // - gateway/graphql/helpers_enum.go + // - gateway/graphql/schema.graphql (enum TradeType) } string id = 1; @@ -303,6 +330,8 @@ enum ChainStatus { CHAIN_STATUS_DISCONNECTED = 1; CHAIN_STATUS_REPLAYING = 2; CHAIN_STATUS_CONNECTED = 3; + + // Note: ChainStatus does not exist in GraphQL. } message NotifyTraderAccount { @@ -364,6 +393,10 @@ enum AccountType { ACCOUNT_TYPE_SETTLEMENT = 2; ACCOUNT_TYPE_MARGIN = 3; ACCOUNT_TYPE_GENERAL = 4; + + // Note: If adding an enum value, add a matching entry in: + // - gateway/graphql/helpers_enum.go + // - gateway/graphql/schema.graphql (enum AccountType) } message Account { diff --git a/script/build.sh b/script/build.sh index 3317e8859b7..b74ff00d465 100755 --- a/script/build.sh +++ b/script/build.sh @@ -12,25 +12,64 @@ alltargets=( \ ) help() { + col="" + nocol="" + if test -t 1 ; then + col="\033[36m" + nocol="\033[0m" + fi echo "Command line arguments:" echo + echo " -a action Take action:" + + grep ')[ ]##' "$0" | awk 'BEGIN {FS = "\)[ ]## "}; {printf "'"$col"'%-20s'"$nocol"' %s\n", $1, $2}' + echo " -d Build debug binaries" - echo " -T Build all available GOOS+GOARCH combinations (see below)" - echo " -t list Build specified GOOS+GOARCH combinations" + echo " -T Build all available GOOS+GOARCH combinations" + echo " -t list Build specified GOOS+GOARCH combinations (comma-separated list)" + + for target in "${alltargets[@]}" ; do + echo -e "\t$col$target$nocol" + done + echo " -s suffix Add arbitrary suffix to compiled binary names" echo " -h Show this help" echo echo "Apps to be built:" for app in "${apps[@]}" ; do - echo " * $app" + echo -e "\t$col$app$nocol" done echo echo "Available targets:" - for target in "${alltargets[@]}" ; do - echo " * $target" - done } +check_golang_version() { + local goprog + goprog="$(command -v go)" + if test -z "$goprog" ; then + echo "Could not find go" + return 1 + fi + + goversion="$("$goprog" version)" + if ! echo "$goversion" | grep -q 'go1\.14\.' ; then + echo "Please use Go 1.14" + echo "Using: $goprog" + echo "Version: $goversion" + return 1 + fi +} + +deps() { + mkdir -p "$GOPATH/pkg/mod/##@explicit" "$GOPATH/pkg/mod/@indirect" && \ + go mod download && \ + go mod vendor && \ + grep 'google/protobuf' go.mod | awk '{print "# " $1 " " $2 "\n"$1"/src";}' >> vendor/modules.txt && \ + grep 'tendermint/tendermint' go.mod | awk '{print "# " $1 " " $2 "\n"$1"/crypto/secp256k1/internal/secp256k1/libsecp256k1";}' >> vendor/modules.txt && \ + modvendor -copy="**/*.c **/*.h **/*.proto" +} + + set_version() { version="${DRONE_TAG:-$(git describe --tags 2>/dev/null)}" version_hash="$(echo "${CI_COMMIT_SHA:-$(git rev-parse HEAD)}" | cut -b1-8)" @@ -60,13 +99,18 @@ set_ldflags() { parse_args() { # set defaults + action="" gcflags="" dbgsuffix="" suffix="" targets=() - while getopts 'ds:Tt:h' flag; do + while getopts 'a:ds:Tt:h' flag + do case "$flag" in + a) + action="$OPTARG" + ;; d) gcflags="all=-N -l" dbgsuffix="-dbg" @@ -91,12 +135,6 @@ parse_args() { ;; esac done - set_ldflags - if test -z "${targets[*]}" ; then - help - else - echo "Version: $version ($version_hash)" - fi } can_build() { @@ -116,24 +154,31 @@ can_build() { return "$canbuild" } -run() { - set_version - parse_args "$@" - - failed=0 - for target in "${targets[@]}" ; do - cc="" - cgo_enabled=1 - cgo_flags="" - cgo_ldflags="" - cgo_cxxflags="" - cxx="" - goarm="" +set_go_flags() { + local target + target="$1" ; shift + cc="" + cgo_cflags="-I$PWD/vendor/github.com/tendermint/tendermint/crypto/secp256k1/internal/secp256k1 -I$PWD/vendor/github.com/tendermint/tendermint/crypto/secp256k1/internal/secp256k1/libsecp256k1" + cgo_ldflags="" + cgo_cxxflags="" + cxx="" + goarm="" + if test "$target" == default ; then + goarch="" + goos="" + osarchsuffix="" + else goarch="$(echo "$target" | cut -f2 -d/)" goos="$(echo "$target" | cut -f1 -d/)" - typesuffix="" - skip=no + osarchsuffix="-$goos-$goarch" + fi + typesuffix="" + skip=no + if test "$action" == build ; then case "$target" in + default) + : + ;; darwin/*) cc=o64-clang cxx=o64-clang++ @@ -170,7 +215,7 @@ run() { cxx=i686-w64-mingw32-g++-posix # https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=vs-2019 win32_winnt="-D_WIN32_WINNT=0x0A00" # Windows 10 - cgo_flags="$win32_winnt" + cgo_cflags="$cgo_cflags $win32_winnt" cgo_cxxflags="$win32_winnt" ;; windows/amd64) @@ -179,7 +224,7 @@ run() { cxx=x86_64-w64-mingw32-g++-posix # https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=vs-2019 win32_winnt="-D_WIN32_WINNT=0x0A00" # Windows 10 - cgo_flags="$win32_winnt" + cgo_cflags="$cgo_cflags $win32_winnt" cgo_cxxflags="$win32_winnt" ;; *) @@ -187,32 +232,124 @@ run() { skip=yes ;; esac + fi + export \ + CC="$cc" \ + CGO_ENABLED=1 \ + CGO_CFLAGS="$cgo_cflags" \ + CGO_LDFLAGS="$cgo_ldflags" \ + CGO_CXXFLAGS="$cgo_cxxflags" \ + CXX="$cxx" \ + GO111MODULE=on \ + GOARCH="$goarch" \ + GOARM="$goarm" \ + GOOS="$goos" \ + GOPROXY=direct \ + GOSUMDB=off + +} +run() { + check_golang_version + parse_args "$@" + if test -z "$action" ; then + help + exit 1 + fi + if test "(" "$action" == build -o "$action" == install ")" -a -z "${targets[*]}" ; then + help + exit 1 + fi + set_version + set_ldflags + echo "Version: $version ($version_hash)" + + set_go_flags default + case "$action" in + build) ## Build apps + : # handled below + ;; + coverage) ## Calculate coverage + c=.testCoverage.txt + go list ./... | grep -v '/gateway' | xargs go test -covermode=count -coverprofile="$c" && \ + go tool cover -func="$c" && \ + go tool cover -html="$c" -o .testCoverage.html + return $? + ;; + deps) ## Get dependencies + deps + return "$?" + ;; + gqlgen) ## Run gqlgen + test -d vendor && mv vendor .vendor.tmp + pushd ./gateway/graphql/ 1>/dev/null || return 1 + go run github.com/99designs/gqlgen --config gqlgen.yml + code="$?" + popd 1>/dev/null || return 1 + test -d .vendor.tmp && mv .vendor.tmp vendor + return "$code" + ;; + install) ## Build apps (in $GOPATH/bin) + : # handled below + ;; + integrationtest) ## Run integration tests (godog) + go test -v ./integration/... -godog.format=pretty + return "$?" + ;; + mocks) ## Generate mocks + go generate ./... + return "$?" + ;; + test) ## Run go test + go test ./... + return "$?" + ;; + race) ## Run go test -race + go test -race ./... + return "$?" + ;; + retest) ## Run go test (and force re-test) + go test -count=1 ./... + return "$?" + ;; + staticcheck) ## Run staticcheck + f="$(mktemp)" + ( + go list ./... | grep -v /integration | xargs staticcheck + find integration -name '*.go' -print0 | xargs -0 staticcheck | grep -v 'could not load export data' + ) | tee "$f" + count="$(wc -l <"$f")" + rm -f "$f" + if test "$count" -gt 0 ; then + return 1 + fi + return 0 + ;; + vet) ## Run go vet + go vet ./... + return "$?" + ;; + *) + echo "Invalid action: $action" + return 1 + esac + + failed=0 + for target in "${targets[@]}" ; do + set_go_flags "$target" if test "$skip" == yes ; then continue fi - can_build "$target" "$cc" "$cxx" || continue - export \ - CC="$cc" \ - CGO_ENABLED="$cgo_enabled" \ - CGO_CFLAGS="$cgo_flags" \ - CGO_LDFLAGS="$cgo_ldflags" \ - CGO_CXXFLAGS="$cgo_cxxflags" \ - CXX="$cxx" \ - GOARCH="$goarch" \ - GOARM="$goarm" \ - GOOS="$goos" - log="/tmp/go.log" - echo "$target: make deps ... " - make deps 1>"$log" 2>&1 + echo "$target: deps ... " + deps 1>"$log" 2>&1 code="$?" if test "$code" = 0 ; then - echo "$target: make deps OK" + echo "$target: deps OK" else - echo "$target: make deps failed ($code)" + echo "$target: deps failed ($code)" failed=$((failed+1)) echo echo "=== BEGIN logs ===" @@ -239,25 +376,42 @@ run() { fi for app in "${apps[@]}" ; do - o="cmd/$app/$app-$goos-$goarch$dbgsuffix$suffix$typesuffix" - log="$o.log" - echo "$target: go build $o ... " - rm -f "$o" "$log" - go build -v -ldflags "$ldflags" -gcflags "$gcflags" -o "$o" "./cmd/$app" 1>"$log" 2>&1 - code="$?" + case "$action" in + build) + o="cmd/$app/$app$osarchsuffix$dbgsuffix$suffix$typesuffix" + log="$o.log" + msgprefix="$target: go $action $o ..." + echo "$msgprefix" + rm -f "$o" "$log" + go build -v -ldflags "$ldflags" -gcflags "$gcflags" -o "$o" "./cmd/$app" 1>"$log" 2>&1 + code="$?" + ;; + install) + o="not/applicable" + log="$app$osarchsuffix$dbgsuffix$suffix$typesuffix.log" + msgprefix="$target: go $action $app ..." + echo "$msgprefix" + rm -f "$log" + go install -v -ldflags "$ldflags" -gcflags "$gcflags" "./cmd/$app" 1>"$log" 2>&1 + code="$?" + ;; + esac if test "$code" = 0 ; then - echo "$target: go build $o OK" + echo "$msgprefix OK" rm "$log" else - echo "$target: go build $o failed ($code)" + echo "$msgprefix failed ($code)" failed=$((failed+1)) echo - echo "=== BEGIN logs for $o ===" + echo "=== BEGIN logs for $msgprefix ===" cat "$log" - echo "=== END logs for $o ===" + echo "=== END logs for $msgprefix ===" fi done done + if test "$failed" -gt 0 ; then + echo "Build failed for $failed apps." + fi return "$failed" } @@ -266,9 +420,5 @@ run() { if echo "$0" | grep -q '/build.sh$' ; then # being run as a script run "$@" - failed="$?" - if test "$failed" -gt 0 ; then - echo "Build failed for $failed apps." - fi - exit "$failed" + exit "$?" fi diff --git a/subscribers/base.go b/subscribers/base.go index b9e708dcb18..d1dab44c337 100644 --- a/subscribers/base.go +++ b/subscribers/base.go @@ -12,6 +12,7 @@ type Base struct { sCh chan struct{} ch chan events.Event running bool + id int } func newBase(ctx context.Context, buf int) *Base { @@ -61,3 +62,13 @@ func (b *Base) Halt() { b.Pause() // close the skip channel close(b.ch) // close the event channel } + +// SetID set the ID (exposed only to broker) +func (b *Base) SetID(id int) { + b.id = id +} + +// ID returns the subscriber ID +func (b *Base) ID() int { + return b.id +} diff --git a/subscribers/trade_event.go b/subscribers/trade_event.go new file mode 100644 index 00000000000..b3d3c66db4e --- /dev/null +++ b/subscribers/trade_event.go @@ -0,0 +1,75 @@ +package subscribers + +import ( + "context" + + "code.vegaprotocol.io/vega/events" + types "code.vegaprotocol.io/vega/proto" +) + +type TE interface { + events.Event + Trade() types.Trade +} + +type TradeStore interface { + SaveBatch([]types.Trade) error +} + +type TradeSub struct { + *Base + buf []types.Trade + store TradeStore +} + +func NewTradeSub(ctx context.Context, store TradeStore) *TradeSub { + t := &TradeSub{ + Base: newBase(ctx, 10), + buf: []types.Trade{}, + store: store, + } + t.running = true + go t.loop(t.ctx) + return t +} + +func (t *TradeSub) loop(ctx context.Context) { + for { + select { + case <-ctx.Done(): + t.Halt() + return + case e := <-t.ch: + if t.running { + t.Push(e) + } + } + } +} + +func (t *TradeSub) Push(e events.Event) { + switch te := e.(type) { + case TE: + t.write(te) + case TimeEvent: + t.flush() + } +} + +// this function will be replaced - this is where the events will be normalised for a market event plugin to use +func (t *TradeSub) write(e TE) { + t.buf = append(t.buf, e.Trade()) +} + +func (t *TradeSub) flush() { + b := t.buf + t.buf = make([]types.Trade, 0, cap(b)) + _ = t.store.SaveBatch(b) +} + +func (t *TradeSub) Types() []events.Type { + return []events.Type{ + events.TradeEvent, + events.TimeUpdate, + } +} diff --git a/validators/topology_test.go b/validators/topology_test.go index e44a5191e0f..58e8bff5c95 100644 --- a/validators/topology_test.go +++ b/validators/topology_test.go @@ -12,7 +12,7 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/tendermint/tendermint/crypto" - cmn "github.com/tendermint/tendermint/libs/common" + "github.com/tendermint/tendermint/libs/bytes" tmctypes "github.com/tendermint/tendermint/rpc/core/types" tmtypes "github.com/tendermint/tendermint/types" ) @@ -37,7 +37,7 @@ func getTestTop(t *testing.T) *testTop { defer func() { ch <- struct{}{} }() return &tmctypes.ResultStatus{ ValidatorInfo: tmctypes.ValidatorInfo{ - Address: cmn.HexBytes([]byte("addresstm")), + Address: bytes.HexBytes([]byte("addresstm")), PubKey: tmTestPubKey(), }, }, nil @@ -48,7 +48,7 @@ func getTestTop(t *testing.T) *testTop { defer func() { ch <- struct{}{} }() return []*tmtypes.Validator{ &tmtypes.Validator{ - Address: cmn.HexBytes([]byte("addresstm")), + Address: bytes.HexBytes([]byte("addresstm")), PubKey: tmTestPubKey(), }, }, nil