Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add market community tags #11239

Draft
wants to merge 2 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions commands/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ var (
ErrInvalidSignature = errors.New("invalid signature")
ErrUnsupportedAlgorithm = errors.New("unsupported algorithm")
ErrEmptyBatchMarketInstructions = errors.New("empty batch market instructions")
ErrIsNotValidVegaID = errors.New("is not a valid vega id")
ErrIsNotValidVegaPubkey = errors.New("is not a valid vega public key")
ErrIsNotValidEthereumAddress = errors.New("is not a valid ethereum address")
ErrEmptyEthereumCallSpec = errors.New("ethereum call spec is required")
Expand Down
22 changes: 22 additions & 0 deletions commands/proposal_submission.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,13 +214,35 @@ func checkProposalChanges(terms *protoTypes.ProposalTerms) Errors {
errs.Merge(checkUpdateReferralProgram(terms, c))
case *protoTypes.ProposalTerms_UpdateVolumeDiscountProgram:
errs.Merge(checkVolumeDiscountProgram(terms, c))
case *protoTypes.ProposalTerms_UpdateMarketCommunityTags:
errs.Merge(checkUpdateMarketCommunityTagsChanges(c))
default:
return errs.FinalAddForProperty("proposal_submission.terms.change", ErrIsNotValid)
}

return errs
}

func checkUpdateMarketCommunityTagsChanges(change *protoTypes.ProposalTerms_UpdateMarketCommunityTags) Errors {
errs := NewErrors()

if change.UpdateMarketCommunityTags == nil {
return errs.FinalAddForProperty("proposal_submission.terms.change.update_market_community_tags", ErrIsRequired)
}

if change.UpdateMarketCommunityTags.Changes == nil {
return errs.FinalAddForProperty("proposal_submission.terms.change.update_market_community_tags.changes", ErrIsRequired)
}

c := change.UpdateMarketCommunityTags.Changes

if !crypto.IsValidVegaID(c.MarketId) {
errs.AddForProperty("proposal_submission.terms.change.update_market_community_tags.changes", ErrIsNotValidVegaID)
}

return errs
}

func checkNetworkParameterUpdateChanges(change *protoTypes.ProposalTerms_UpdateNetworkParameter) Errors {
errs := NewErrors()

Expand Down
5 changes: 4 additions & 1 deletion core/events/bus.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ const (
VolumeRebateProgramEndedEvent
VolumeRebateProgramUpdatedEvent
VolumeRebateStatsUpdatedEvent
MarketCommunityTagsEvent
)

var (
Expand Down Expand Up @@ -285,6 +286,7 @@ var (
eventspb.BusEventType_BUS_EVENT_TYPE_VOLUME_REBATE_PROGRAM_ENDED: VolumeRebateProgramEndedEvent,
eventspb.BusEventType_BUS_EVENT_TYPE_VOLUME_REBATE_PROGRAM_UPDATED: VolumeRebateProgramUpdatedEvent,
eventspb.BusEventType_BUS_EVENT_TYPE_VOLUME_REBATE_STATS_UPDATED: VolumeRebateStatsUpdatedEvent,
eventspb.BusEventType_BUS_EVENT_TYPE_MARKET_COMMUNITY_TAG: MarketCommunityTagsEvent,
// If adding a type here, please also add it to datanode/broker/convert.go
}

Expand Down Expand Up @@ -383,7 +385,7 @@ var (
VolumeRebateProgramEndedEvent: eventspb.BusEventType_BUS_EVENT_TYPE_VOLUME_REBATE_PROGRAM_ENDED,
VolumeRebateProgramUpdatedEvent: eventspb.BusEventType_BUS_EVENT_TYPE_VOLUME_REBATE_PROGRAM_UPDATED,
VolumeRebateStatsUpdatedEvent: eventspb.BusEventType_BUS_EVENT_TYPE_VOLUME_REBATE_STATS_UPDATED,

MarketCommunityTagsEvent: eventspb.BusEventType_BUS_EVENT_TYPE_MARKET_COMMUNITY_TAG,
// If adding a type here, please also add it to datanode/broker/convert.go
}

Expand Down Expand Up @@ -481,6 +483,7 @@ var (
VolumeRebateProgramEndedEvent: "VolumeRebateProgramEndedEvent",
VolumeRebateProgramUpdatedEvent: "VolumeRebateProgramUpdatedEvent",
VolumeRebateStatsUpdatedEvent: "VolumeRebateStatsUpdatedEvent",
MarketCommunityTagsEvent: "MarketCommunityTagsEvent",
}
)

Expand Down
57 changes: 57 additions & 0 deletions core/events/market_community_tags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (C) 2023 Gobalsky Labs Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

package events

import (
"context"

eventspb "code.vegaprotocol.io/vega/protos/vega/events/v1"
)

type MarketCommunityTags struct {
*Base
a eventspb.MarketCommunityTags
}

func NewMarketCommunityTagsEvent(ctx context.Context, e eventspb.MarketCommunityTags) *MarketCommunityTags {
return &MarketCommunityTags{
Base: newBase(ctx, MarketCommunityTagsEvent),
a: e,
}
}

func (a *MarketCommunityTags) MarketCommunityTags() eventspb.MarketCommunityTags {
return a.a
}

func (a MarketCommunityTags) Proto() eventspb.MarketCommunityTags {
return a.a
}

func (a MarketCommunityTags) StreamMessage() *eventspb.BusEvent {
busEvent := newBusEventFromBase(a.Base)
busEvent.Event = &eventspb.BusEvent_MarketCommunityTags{
MarketCommunityTags: &a.a,
}
return busEvent
}

func MarketCommunityTagsEventFromStream(ctx context.Context, be *eventspb.BusEvent) *MarketCommunityTags {
return &MarketCommunityTags{
Base: newBaseFromBusEvent(ctx, MarketCommunityTagsEvent, be),
a: *be.GetMarketCommunityTags(),
}
}
23 changes: 19 additions & 4 deletions core/execution/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ type Engine struct {
allMarkets map[string]common.CommonMarket
allMarketsCpy []common.CommonMarket

communityTags *MarketCommunityTags
collateral common.Collateral
assets common.Assets
referralDiscountRewardService fee.ReferralDiscountRewardService
Expand Down Expand Up @@ -169,10 +170,10 @@ func NewEngine(
referralDiscountRewardService: referralDiscountRewardService,
volumeDiscountService: volumeDiscountService,
volumeRebateService: volumeRebateService,

banking: banking,
parties: parties,
delayTransactionsTarget: delayTransactionsTarget,
banking: banking,
parties: parties,
delayTransactionsTarget: delayTransactionsTarget,
communityTags: NewMarketCommunityTags(broker),
}

// set the eligibility for proposer bonus checker
Expand Down Expand Up @@ -1563,3 +1564,17 @@ func (e *Engine) GetFillPriceForMarket(marketID string, volume uint64, side type
}
return nil, types.ErrInvalidMarketID
}

func (e *Engine) UpdateCommunityTags(
ctx context.Context,
market string,
addTags []string,
removeTags []string,
) {
// has the market been removed since the proposal was created?
if !e.MarketExists(market) {
return
}

e.communityTags.UpdateTags(ctx, market, addTags, removeTags)
}
16 changes: 11 additions & 5 deletions core/execution/engine_snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,14 +317,17 @@ func (e *Engine) serialise() (snapshot []byte, providers []types.StateProvider,
allMarketIDs = append(allMarketIDs, cm.GetID())
}

tags := e.communityTags.serialize()

pl := types.Payload{
Data: &types.PayloadExecutionMarkets{
ExecutionMarkets: &types.ExecutionMarkets{
Markets: mkts,
SpotMarkets: spotMkts,
SettledMarkets: cpStates,
Successors: successors,
AllMarketIDs: allMarketIDs,
Markets: mkts,
SpotMarkets: spotMkts,
SettledMarkets: cpStates,
Successors: successors,
AllMarketIDs: allMarketIDs,
MarketCommunityTags: tags,
},
},
}
Expand Down Expand Up @@ -383,6 +386,9 @@ func (e *Engine) LoadState(ctx context.Context, payload *types.Payload) ([]types
e.allMarketsCpy = append(e.allMarketsCpy, mkt)
}
}

e.communityTags = NewMarketCommunityTagFromProto(e.broker, pl.ExecutionMarkets.MarketCommunityTags)

return append(providers, spotProviders...), err
default:
return nil, types.ErrUnknownSnapshotType
Expand Down
107 changes: 107 additions & 0 deletions core/execution/market_community_tags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright (C) 2023 Gobalsky Labs Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

package execution

import (
"context"
"sort"

"code.vegaprotocol.io/vega/core/events"
"code.vegaprotocol.io/vega/core/execution/common"
eventspb "code.vegaprotocol.io/vega/protos/vega/events/v1"

"golang.org/x/exp/maps"
)

type MarketCommunityTags struct {
// market id -> set of tags
tags map[string]map[string]struct{}
broker common.Broker
}

func NewMarketCommunityTags(broker common.Broker) *MarketCommunityTags {
return &MarketCommunityTags{
tags: map[string]map[string]struct{}{},
broker: broker,
}
}

func NewMarketCommunityTagFromProto(
broker common.Broker,
state []*eventspb.MarketCommunityTags,
) *MarketCommunityTags {
m := NewMarketCommunityTags(broker)

for _, v := range state {
m.tags[v.MarketId] = map[string]struct{}{}
for _, t := range v.Tags {
m.tags[v.MarketId][t] = struct{}{}
}
}

return m
}

func (m *MarketCommunityTags) serialize() []*eventspb.MarketCommunityTags {
out := make([]*eventspb.MarketCommunityTags, 0, len(m.tags))

for mkt, tags := range m.tags {
mct := &eventspb.MarketCommunityTags{
MarketId: mkt,
Tags: make([]string, 0, len(tags)),
}

for tag := range tags {
mct.Tags = append(mct.Tags, tag)
}

sort.Strings(mct.Tags)
}

sort.Slice(out, func(i, j int) bool { return out[i].MarketId < out[j].MarketId })

return out
}

// UpdateTags by that point the tags have been validated in length,
// so no need to do that again.
func (m *MarketCommunityTags) UpdateTags(
ctx context.Context,
market string,
addTags []string,
removeTags []string,
) {
tags, ok := m.tags[market]
if !ok {
tags = map[string]struct{}{}
}

for _, t := range addTags {
tags[t] = struct{}{}
}

for _, t := range removeTags {
delete(tags, t)
}

evt := eventspb.MarketCommunityTags{
MarketId: market,
Tags: maps.Keys(tags),
}

sort.Strings(evt.Tags)
m.broker.Send(events.NewMarketCommunityTagsEvent(ctx, evt))
}
17 changes: 17 additions & 0 deletions core/governance/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ var (
ErrParentMarketAlreadySucceeded = errors.New("the parent market was already succeeded by a prior proposal")
ErrParentMarketSucceededByCompeting = errors.New("the parent market has been succeeded by a competing propsal")
ErrSettlementDataOutOfRange = errors.New("the settlement data is invalid")
ErrUnknownMarketID = func(id string) error {
return fmt.Errorf("unknown market id %v", id)
}
)

//go:generate go run github.com/golang/mock/mockgen -destination mocks/mocks.go -package mocks code.vegaprotocol.io/vega/core/governance Markets,StakingAccounts,Assets,TimeService,Witness,NetParams,Banking
Expand Down Expand Up @@ -298,6 +301,8 @@ func (e *Engine) preEnactProposal(ctx context.Context, p *proposal) (te *ToEnact
te.volumeDiscountProgram = updatedVolumeDiscountProgramFromProposal(p)
case types.ProposalTermsTypeUpdateVolumeRebateProgram:
te.volumeRebateProgram = updatedVolumeRebateProgramFromProposal(p)
case types.ProposalTermsTypeUpdateMarketCommunityTags:
te.updateMarketCommunityTags = p.UpdateMarketCommunityTags()
}
return //nolint:nakedret
}
Expand Down Expand Up @@ -745,6 +750,8 @@ func (e *Engine) getProposalParams(proposalTerm types.ProposalTerm) (*types.Prop
return e.getVolumeDiscountProgramNetworkParameters(), nil
case types.ProposalTermsTypeUpdateVolumeRebateProgram:
return e.getVolumeRebateProgramNetworkParameters(), nil
case types.ProposalTermsTypeUpdateMarketCommunityTags:
return e.getUpdateMarketCommunityTagsParameters(), nil
default:
return nil, ErrUnsupportedProposalType
}
Expand Down Expand Up @@ -1097,11 +1104,21 @@ func (e *Engine) validateChange(terms *types.ProposalTerms) (types.ProposalError
return validateUpdateVolumeDiscountProgram(e.netp, terms.GetUpdateVolumeDiscountProgram())
case types.ProposalTermsTypeUpdateVolumeRebateProgram:
return validateUpdateVolumeRebateProgram(e.netp, terms.GetUpdateVolumeRebateProgram())
case types.ProposalTermsTypeUpdateMarketCommunityTags:
return validateUpdateMarketCommunityTags(terms.GetUpdateMarketCommunityTags(), e.markets)
default:
return types.ProposalErrorUnspecified, nil
}
}

func validateUpdateMarketCommunityTags(p *types.UpdateMarketCommunityTags, markets Markets) (types.ProposalError, error) {
if !markets.MarketExists(p.MarketID) {
return types.ProposalErrorUnknownMarketID, ErrUnknownMarketID(p.MarketID)
}

return types.ProposalErrorUnspecified, nil
}

func (e *Engine) validateGovernanceTransfer(newTransfer *types.NewTransfer) (types.ProposalError, error) {
if err := e.banking.VerifyGovernanceTransfer(newTransfer.Changes); err != nil {
return types.ProporsalErrorInvalidGovernanceTransfer, err
Expand Down
16 changes: 16 additions & 0 deletions core/governance/netparams.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,22 @@ func (e *Engine) getVolumeRebateProgramNetworkParameters() *types.ProposalParame
)
}

func (e *Engine) getUpdateMarketCommunityTagsParameters() *types.ProposalParameters {
return e.getProposalParametersFromNetParams(
netparams.GovernanceProposalUpdateCommunityTagsMinClose,
netparams.GovernanceProposalUpdateCommunityTagsMaxClose,
netparams.GovernanceProposalUpdateCommunityTagsMinEnact,
netparams.GovernanceProposalUpdateCommunityTagsMaxEnact,
netparams.GovernanceProposalUpdateCommunityTagsRequiredParticipation,
netparams.GovernanceProposalUpdateCommunityTagsRequiredMajority,
netparams.GovernanceProposalUpdateCommunityTagsMinProposerBalance,
netparams.GovernanceProposalUpdateCommunityTagsMinVoterBalance,
"0",
"0",
"0",
)
}

func (e *Engine) getNewAssetProposalParameters() *types.ProposalParameters {
return e.getProposalParametersFromNetParams(
netparams.GovernanceProposalAssetMinClose,
Expand Down
Loading
Loading