Skip to content

Commit

Permalink
feat: long block auction
Browse files Browse the repository at this point in the history
  • Loading branch information
ze97286 committed Jun 24, 2024
1 parent 7c4577b commit 4b4b245
Show file tree
Hide file tree
Showing 37 changed files with 2,379 additions and 1,720 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
- [11357](https://github.com/vegaprotocol/vega/issues/11357) - Support historical game scores
- [11023](https://github.com/vegaprotocol/vega/issues/11023) - Add proposed fees to `vAMM` data.
- [11028](https://github.com/vegaprotocol/vega/issues/11028) - Add API to estimate order book depth based on `vAMM`.
- [11400](https://github.com/vegaprotocol/vega/issues/11400) - Add support for long block auction.

### 🐛 Fixes

Expand Down
3 changes: 3 additions & 0 deletions core/execution/common/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ type AuctionState interface {
price.AuctionState
// are we in auction, and what auction are we in?
ExtendAuctionSuspension(delta types.AuctionDuration)
ExtendAuctionLongBlock(delta types.AuctionDuration)
InAuction() bool
IsOpeningAuction() bool
IsPriceAuction() bool
Expand Down Expand Up @@ -128,6 +129,7 @@ type AuctionState interface {
Changed() bool
UpdateMaxDuration(ctx context.Context, d time.Duration)
StartGovernanceSuspensionAuction(t time.Time)
StartLongBlockAuction(t time.Time, d int64)
EndGovernanceSuspensionAuction()
}

Expand Down Expand Up @@ -361,6 +363,7 @@ type CommonMarket interface {
UpdateMarketState(ctx context.Context, changes *types.MarketStateUpdateConfiguration) error
GetFillPrice(volume uint64, side types.Side) (*num.Uint, error)
Mkt() *types.Market
EnterLongBlockAuction(ctx context.Context, duration int64)

IsOpeningAuction() bool

Expand Down
24 changes: 24 additions & 0 deletions core/execution/common/mocks/mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 15 additions & 1 deletion core/execution/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,12 @@ func (e *Engine) StartOpeningAuction(ctx context.Context, marketID string) error
return ErrMarketDoesNotExist
}

func (e *Engine) EnterLongBlockAuction(ctx context.Context, duration int64) {
for _, mkt := range e.allMarkets {
mkt.EnterLongBlockAuction(ctx, duration)
}
}

func (e *Engine) SucceedMarket(ctx context.Context, successor, parent string) error {
return e.succeedOrRestore(ctx, successor, parent, false)
}
Expand Down Expand Up @@ -1383,10 +1389,18 @@ func (e *Engine) BlockEnd(ctx context.Context) {
}
}

func (e *Engine) BeginBlock(ctx context.Context) {
func (e *Engine) BeginBlock(ctx context.Context, prevBlockDuration time.Duration) {
for _, mkt := range e.allMarketsCpy {
mkt.BeginBlock(ctx)
}
longBlockAuctionDuration := e.npv.lbadTable.GetLongBlockAuctionDurationForBlockDuration(prevBlockDuration)
if longBlockAuctionDuration == nil {
return
}
auctionDurationInSeconds := int64(longBlockAuctionDuration.Seconds())
for _, mkt := range e.allMarketsCpy {
mkt.EnterLongBlockAuction(ctx, auctionDurationInSeconds)
}
}

func (e *Engine) GetMarketState(mktID string) (types.MarketState, error) {
Expand Down
21 changes: 21 additions & 0 deletions core/execution/engine_netparams.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ type netParamsValues struct {

// only used for protocol upgrade to v0.74
chainID uint64

// network wide auction duration
lbadTable *types.LongBlockAuctionDurationTable
}

func defaultNetParamsValues() netParamsValues {
Expand Down Expand Up @@ -273,6 +276,24 @@ func (e *Engine) OnMarketLiquidityV2ProvidersFeeCalculationTimeStep(_ context.Co
return nil
}

func (e *Engine) OnNetworkWideAuctionDurationUpdated(ctx context.Context, v interface{}) error {
if e.log.IsDebug() {
e.log.Debug("update network wide auction duration",
logging.Reflect("network-wide-auction-duration", v),
)
}
lbadTable, ok := v.(*vega.LongBlockAuctionDurationTable)
if !ok {
return errors.New("invalid long block auction duration table")
}
lbads, err := types.LongBlockAuctionDurationTableFromProto(lbadTable)
if err != nil {
return err
}
e.npv.lbadTable = lbads
return nil
}

func (e *Engine) OnMarketMarginScalingFactorsUpdate(ctx context.Context, v interface{}) error {
if e.log.IsDebug() {
e.log.Debug("update market scaling factors",
Expand Down
17 changes: 17 additions & 0 deletions core/execution/future/market.go
Original file line number Diff line number Diff line change
Expand Up @@ -1498,6 +1498,23 @@ func (m *Market) uncrossOrderAtAuctionEnd(ctx context.Context) {
m.uncrossOnLeaveAuction(ctx)
}

func (m *Market) EnterLongBlockAuction(ctx context.Context, duration int64) {
m.mkt.State = types.MarketStateSuspended
m.mkt.TradingMode = types.MarketTradingModelLongBlockAuction
if m.as.InAuction() {
m.as.ExtendAuctionLongBlock(types.AuctionDuration{Duration: duration})
evt := m.as.AuctionExtended(ctx, m.timeService.GetTimeNow())
if evt != nil {
m.broker.Send(evt)
}
} else {
m.as.StartLongBlockAuction(m.timeService.GetTimeNow(), duration)
m.tradableInstrument.Instrument.UpdateAuctionState(ctx, true)
m.enterAuction(ctx)
m.broker.Send(events.NewMarketUpdatedEvent(ctx, *m.mkt))
}
}

func (m *Market) UpdateMarketState(ctx context.Context, changes *types.MarketStateUpdateConfiguration) error {
_, blockHash := vegacontext.TraceIDFromContext(ctx)
// make deterministic ID for this market, concatenate
Expand Down
16 changes: 16 additions & 0 deletions core/execution/spot/market.go
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,22 @@ func (m *Market) uncrossOrderAtAuctionEnd(ctx context.Context) {
m.uncrossOnLeaveAuction(ctx)
}

func (m *Market) EnterLongBlockAuction(ctx context.Context, duration int64) {
m.mkt.State = types.MarketStateSuspended
m.mkt.TradingMode = types.MarketTradingModelLongBlockAuction
if m.as.InAuction() {
m.as.ExtendAuctionLongBlock(types.AuctionDuration{Duration: duration})
evt := m.as.AuctionExtended(ctx, m.timeService.GetTimeNow())
if evt != nil {
m.broker.Send(evt)
}
} else {
m.as.StartLongBlockAuction(m.timeService.GetTimeNow(), duration)
m.enterAuction(ctx)
m.broker.Send(events.NewMarketUpdatedEvent(ctx, *m.mkt))
}
}

func (m *Market) UpdateMarketState(ctx context.Context, changes *types.MarketStateUpdateConfiguration) error {
_, blockHash := vegacontext.TraceIDFromContext(ctx)
// make deterministic ID for this market, concatenate
Expand Down
7 changes: 7 additions & 0 deletions core/integration/stubs/time_stub.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ func (t *TimeStub) SetTimeNow(_ context.Context, newNow time.Time) {
t.SetTime(newNow)
}

func (t *TimeStub) SetPrevTime(newNow time.Time) {
}

func (t *TimeStub) GetTimeLastBatch() time.Time {
return time.Time{}
}

func (t *TimeStub) SetTime(newNow time.Time) {
t.now = newNow
ctx := vegacontext.WithTraceID(context.Background(), vgcrypto.RandomHash())
Expand Down
17 changes: 17 additions & 0 deletions core/monitor/auction.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,15 @@ func (a *AuctionState) StartPriceAuction(t time.Time, d *types.AuctionDuration)
a.end = d
}

func (a *AuctionState) StartLongBlockAuction(t time.Time, d int64) {
a.mode = types.MarketTradingModelLongBlockAuction
a.trigger = types.AuctionTriggerLongBlock
a.start = true
a.stop = false
a.begin = &t
a.end = &types.AuctionDuration{Duration: d}
}

func (a *AuctionState) StartGovernanceSuspensionAuction(t time.Time) {
a.mode = types.MarketTradingModeSuspendedViaGovernance
a.trigger = types.AuctionTriggerGovernanceSuspension
Expand Down Expand Up @@ -156,6 +165,14 @@ func (a *AuctionState) ExtendAuctionPrice(delta types.AuctionDuration) {
a.ExtendAuction(delta)
}

func (a *AuctionState) ExtendAuctionLongBlock(delta types.AuctionDuration) {
t := types.AuctionTriggerLongBlock
if a.trigger != t {
a.extension = &t
}
a.ExtendAuction(delta)
}

func (a *AuctionState) ExtendAuctionSuspension(delta types.AuctionDuration) {
t := types.AuctionTriggerGovernanceSuspension
a.extension = &t
Expand Down
31 changes: 31 additions & 0 deletions core/netparams/checks/checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,37 @@ func SpamPoWHashFunction(supportedFunctions []string) func(string) error {
}
}

func LongBlockAuctionDurationTable() func(interface{}, interface{}) error {
return func(v interface{}, _ interface{}) error {
lbadTable, ok := v.(*types.LongBlockAuctionDurationTable)
if !ok {
return fmt.Errorf("invalid long block auction duration table")
}
seenThresholds := map[string]struct{}{}
for i, tad := range lbadTable.ThresholdAndDuration {
thr, err := time.ParseDuration(tad.Threshold)
if err != nil {
return fmt.Errorf("invalid long block auction duration table - threshold at index %d is not a valid duration", i)
}
if thr.Nanoseconds() <= 0 {
return fmt.Errorf("invalid long block auction duration table - threshold at index %d is not a positive duration", i)
}
dur, err := time.ParseDuration(tad.Duration)
if err != nil {
return fmt.Errorf("invalid long block auction duration table - duration at index %d is not a valid duration", i)
}
if dur.Nanoseconds() <= 0 {
return fmt.Errorf("invalid long block auction duration table - duration at index %d is not a positive duration", i)
}
if _, ok := seenThresholds[tad.Threshold]; ok {
return fmt.Errorf("invalid long block auction duration table - duplicate threshold")
}
seenThresholds[tad.Threshold] = struct{}{}
}
return nil
}
}

func MarginScalingFactor() func(interface{}, interface{}) error {
return func(v interface{}, _ interface{}) error {
sf := v.(*types.ScalingFactors)
Expand Down
91 changes: 91 additions & 0 deletions core/netparams/checks/checks_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// 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 checks_test

import (
"testing"

"code.vegaprotocol.io/vega/core/netparams/checks"
types "code.vegaprotocol.io/vega/protos/vega"

"github.com/stretchr/testify/require"
)

func TestLongBlockChecks(t *testing.T) {
// wrong type - error
type Junk struct{}
require.Equal(t, "invalid long block auction duration table", checks.LongBlockAuctionDurationTable()(&Junk{}, &Junk{}).Error())

// empty - is fine
table := &types.LongBlockAuctionDurationTable{}
require.NoError(t, checks.LongBlockAuctionDurationTable()(table, nil))

// invalid threshold at index 0 - error
table.ThresholdAndDuration = []*types.LongBlockAuction{{Threshold: "banana", Duration: "1s"}}
require.Equal(t, "invalid long block auction duration table - threshold at index 0 is not a valid duration", checks.LongBlockAuctionDurationTable()(table, nil).Error())

table.ThresholdAndDuration = []*types.LongBlockAuction{{Threshold: "-1", Duration: "1s"}}
require.Equal(t, "invalid long block auction duration table - threshold at index 0 is not a valid duration", checks.LongBlockAuctionDurationTable()(table, nil).Error())

table.ThresholdAndDuration = []*types.LongBlockAuction{{Threshold: "-1s", Duration: "1s"}}
require.Equal(t, "invalid long block auction duration table - threshold at index 0 is not a positive duration", checks.LongBlockAuctionDurationTable()(table, nil).Error())

table.ThresholdAndDuration = []*types.LongBlockAuction{{Threshold: "0s", Duration: "1s"}}
require.Equal(t, "invalid long block auction duration table - threshold at index 0 is not a positive duration", checks.LongBlockAuctionDurationTable()(table, nil).Error())

// invalid duration a index 0 - error
table.ThresholdAndDuration = []*types.LongBlockAuction{{Threshold: "1s", Duration: "banana"}}
require.Equal(t, "invalid long block auction duration table - duration at index 0 is not a valid duration", checks.LongBlockAuctionDurationTable()(table, nil).Error())

table.ThresholdAndDuration = []*types.LongBlockAuction{{Threshold: "1s", Duration: "-1"}}
require.Equal(t, "invalid long block auction duration table - duration at index 0 is not a valid duration", checks.LongBlockAuctionDurationTable()(table, nil).Error())

table.ThresholdAndDuration = []*types.LongBlockAuction{{Threshold: "1s", Duration: "-1s"}}
require.Equal(t, "invalid long block auction duration table - duration at index 0 is not a positive duration", checks.LongBlockAuctionDurationTable()(table, nil).Error())

table.ThresholdAndDuration = []*types.LongBlockAuction{{Threshold: "1s", Duration: "0s"}}
require.Equal(t, "invalid long block auction duration table - duration at index 0 is not a positive duration", checks.LongBlockAuctionDurationTable()(table, nil).Error())

// invalid threshold at index 1 - error
table.ThresholdAndDuration = []*types.LongBlockAuction{{Threshold: "1s", Duration: "1s"}, {Threshold: "banana", Duration: "1s"}}
require.Equal(t, "invalid long block auction duration table - threshold at index 1 is not a valid duration", checks.LongBlockAuctionDurationTable()(table, nil).Error())

table.ThresholdAndDuration = []*types.LongBlockAuction{{Threshold: "1s", Duration: "1s"}, {Threshold: "-1", Duration: "1s"}}
require.Equal(t, "invalid long block auction duration table - threshold at index 1 is not a valid duration", checks.LongBlockAuctionDurationTable()(table, nil).Error())

table.ThresholdAndDuration = []*types.LongBlockAuction{{Threshold: "1s", Duration: "1s"}, {Threshold: "-1s", Duration: "1s"}}
require.Equal(t, "invalid long block auction duration table - threshold at index 1 is not a positive duration", checks.LongBlockAuctionDurationTable()(table, nil).Error())

table.ThresholdAndDuration = []*types.LongBlockAuction{{Threshold: "1s", Duration: "1s"}, {Threshold: "0s", Duration: "1s"}}
require.Equal(t, "invalid long block auction duration table - threshold at index 1 is not a positive duration", checks.LongBlockAuctionDurationTable()(table, nil).Error())

// invalid duration a index 1 - error
table.ThresholdAndDuration = []*types.LongBlockAuction{{Threshold: "1s", Duration: "1s"}, {Threshold: "1s", Duration: "banana"}}
require.Equal(t, "invalid long block auction duration table - duration at index 1 is not a valid duration", checks.LongBlockAuctionDurationTable()(table, nil).Error())

table.ThresholdAndDuration = []*types.LongBlockAuction{{Threshold: "1s", Duration: "1s"}, {Threshold: "1s", Duration: "-1"}}
require.Equal(t, "invalid long block auction duration table - duration at index 1 is not a valid duration", checks.LongBlockAuctionDurationTable()(table, nil).Error())

table.ThresholdAndDuration = []*types.LongBlockAuction{{Threshold: "1s", Duration: "1s"}, {Threshold: "1s", Duration: "-1s"}}
require.Equal(t, "invalid long block auction duration table - duration at index 1 is not a positive duration", checks.LongBlockAuctionDurationTable()(table, nil).Error())

table.ThresholdAndDuration = []*types.LongBlockAuction{{Threshold: "1s", Duration: "1s"}, {Threshold: "1s", Duration: "0s"}}
require.Equal(t, "invalid long block auction duration table - duration at index 1 is not a positive duration", checks.LongBlockAuctionDurationTable()(table, nil).Error())

// duplicate threshold - error
table.ThresholdAndDuration = []*types.LongBlockAuction{{Threshold: "1s", Duration: "1s"}, {Threshold: "1s", Duration: "100s"}}
require.Equal(t, "invalid long block auction duration table - duplicate threshold", checks.LongBlockAuctionDurationTable()(table, nil).Error())
}
1 change: 1 addition & 0 deletions core/netparams/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ var (

func defaultNetParams() map[string]value {
m := map[string]value{
NetworkWideAuctionDuration: NewJSON(&proto.LongBlockAuctionDurationTable{}, checks.LongBlockAuctionDurationTable()).Mutable(true).MustUpdate(`{"threshold_and_duration": [{"threshold":"30s","duration":"1m"},{"threshold":"40s","duration":"10m"},{"threshold":"2m","duration":"1h"}]}`),
MinimalMarginQuantumMultiple: NewDecimal(gteD0).Mutable(true).MustUpdate("0"),
MinimalHoldingQuantumMultiple: NewDecimal(gteD0).Mutable(true).MustUpdate("0"),

Expand Down
3 changes: 3 additions & 0 deletions core/netparams/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ const (
AMMMarketTradingEnabled = "limits.markets.ammPoolEnabled"
EthereumOraclesEnabled = "ethereum.oracles.enabled"

NetworkWideAuctionDuration = "network.wide.auctionDuration"

MarketMarginScalingFactors = "market.margin.scalingFactors"
MarketFeeFactorsMakerFee = "market.fee.factors.makerFee"
MarketFeeFactorsInfrastructureFee = "market.fee.factors.infrastructureFee"
Expand Down Expand Up @@ -282,6 +284,7 @@ var Deprecated = map[string]struct{}{
}

var AllKeys = map[string]struct{}{
NetworkWideAuctionDuration: {},
RewardsUpdateFrequency: {},
SpamProtectionMaxUpdatePartyProfile: {},
SpamProtectionUpdateProfileMinFunds: {},
Expand Down
3 changes: 2 additions & 1 deletion core/processor/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -1342,7 +1342,8 @@ func (app *App) OnBeginBlock(blockHeight uint64, blockHash string, blockTime tim
app.protocolUpgradeService.BeginBlock(ctx, blockHeight)
app.top.BeginBlock(ctx, blockHeight, proposer)
app.balanceChecker.BeginBlock(ctx)
app.exec.BeginBlock(ctx)
blockDuration := app.currentTimestamp.Sub(app.previousTimestamp)
app.exec.BeginBlock(ctx, blockDuration)
return ctx
}

Expand Down
Loading

0 comments on commit 4b4b245

Please sign in to comment.