Skip to content

Commit

Permalink
feat: Slinky full integration PR (#1141)
Browse files Browse the repository at this point in the history
* Squashed commit of the following:

commit 96d900d
Author: Eric <eric.warehime@gmail.com>
Date:   Tue Mar 5 08:51:29 2024 -0800

    Fix non-initialized return values

commit 9ec7992
Author: Eric <eric.warehime@gmail.com>
Date:   Tue Mar 5 08:42:48 2024 -0800

    Upstream compat

commit 47809c7
Merge: 7607b9e f6b594c
Author: Eric <eric.warehime@gmail.com>
Date:   Tue Mar 5 08:40:34 2024 -0800

    Merge remote-tracking branch 'upstream' into eric/protocol-feature-flags

commit 7607b9e
Author: Eric <eric.warehime@gmail.com>
Date:   Mon Mar 4 14:58:06 2024 -0800

    Fix accidental deletes

commit 297b592
Author: Eric <eric.warehime@gmail.com>
Date:   Mon Mar 4 14:22:06 2024 -0800

    Merge

commit 6c32623
Merge: 5811502 daad125
Author: Eric <eric.warehime@gmail.com>
Date:   Mon Mar 4 13:50:26 2024 -0800

    Merge remote-tracking branch 'origin/eric/ve-logic' into eric/protocol-feature-flags

commit 5811502
Merge: 6adf756 7feaddb
Author: Eric <eric.warehime@gmail.com>
Date:   Mon Mar 4 13:49:23 2024 -0800

    Merge remote-tracking branch 'origin/eric/proposal-logic' into eric/protocol-feature-flags

commit 6adf756
Merge: c84eb82 88675f5
Author: Eric <eric.warehime@gmail.com>
Date:   Mon Mar 4 13:44:46 2024 -0800

    Merge remote-tracking branch 'origin/eric/sidecar-integration' into eric/protocol-feature-flags

commit daad125
Author: Eric <eric.warehime@gmail.com>
Date:   Mon Mar 4 10:51:23 2024 -0800

    VoteExtension slinky logic

commit 7feaddb
Author: Eric <eric.warehime@gmail.com>
Date:   Sun Mar 3 21:28:32 2024 -0800

    Fix import order

commit 382d45c
Author: Eric <eric.warehime@gmail.com>
Date:   Sun Mar 3 21:24:41 2024 -0800

    Prepare and Process logic for Slinky

commit 88675f5
Author: Eric <eric.warehime@gmail.com>
Date:   Tue Feb 27 12:46:33 2024 -0800

    Register daemon with health monitor

commit 8438d54
Author: Eric <eric.warehime@gmail.com>
Date:   Tue Feb 27 12:32:36 2024 -0800

    PR updates

commit 3046d69
Author: Eric <eric.warehime@gmail.com>
Date:   Mon Feb 26 15:05:52 2024 -0800

    Make unflaky

commit 7799d29
Author: Eric <eric.warehime@gmail.com>
Date:   Mon Feb 26 15:01:18 2024 -0800

    Lints, more tests

commit e0a8c37
Author: Eric <eric.warehime@gmail.com>
Date:   Mon Feb 26 14:35:11 2024 -0800

    Add tests

commit d8e5e90
Author: Eric <eric.warehime@gmail.com>
Date:   Sat Feb 24 21:01:35 2024 -0800

    Add interfaces, generate mocks

commit 3a8ebec
Author: Eric <eric.warehime@gmail.com>
Date:   Sat Feb 24 10:18:33 2024 -0800

    Lint

commit 5cdd35f
Author: Eric <eric.warehime@gmail.com>
Date:   Sat Feb 24 10:09:56 2024 -0800

    Initial commit of sidecar integration

* Don't update min_exchanges

* go mod tidy

* Fix error

* Update sample pregenesis

* Remove unncessary updates

* Update flags and handlers

* Don't chain mock makefile

* Remove oracle_client

* Update init

* Update opts

* update app

* Fix rewards test

* Fix clob tests

* Fix prices cli test
  • Loading branch information
Eric-Warehime authored Mar 20, 2024
1 parent 75cc26a commit 12e9e28
Show file tree
Hide file tree
Showing 23 changed files with 1,318 additions and 873 deletions.
223 changes: 169 additions & 54 deletions protocol/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,10 @@ import (
"github.com/cosmos/ibc-go/modules/capability"
capabilitykeeper "github.com/cosmos/ibc-go/modules/capability/keeper"
capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types"
"github.com/dydxprotocol/v4-chain/protocol/daemons/configs"
"github.com/gorilla/mux"
"github.com/rakyll/statik/fs"
"github.com/spf13/cast"
"go.uber.org/zap"
"google.golang.org/grpc"

// App
Expand All @@ -103,6 +103,7 @@ import (
"github.com/dydxprotocol/v4-chain/protocol/app/prepare/prices"
"github.com/dydxprotocol/v4-chain/protocol/app/process"

"github.com/dydxprotocol/v4-chain/protocol/app/vote_extensions"
"github.com/dydxprotocol/v4-chain/protocol/lib"
"github.com/dydxprotocol/v4-chain/protocol/lib/metrics"
timelib "github.com/dydxprotocol/v4-chain/protocol/lib/time"
Expand All @@ -113,6 +114,7 @@ import (

// Daemons
bridgeclient "github.com/dydxprotocol/v4-chain/protocol/daemons/bridge/client"
"github.com/dydxprotocol/v4-chain/protocol/daemons/configs"
daemonflags "github.com/dydxprotocol/v4-chain/protocol/daemons/flags"
liquidationclient "github.com/dydxprotocol/v4-chain/protocol/daemons/liquidation/client"
metricsclient "github.com/dydxprotocol/v4-chain/protocol/daemons/metrics/client"
Expand Down Expand Up @@ -205,9 +207,16 @@ import (
"github.com/dydxprotocol/v4-chain/protocol/indexer/msgsender"

// Slinky
slinkyproposals "github.com/skip-mev/slinky/abci/proposals"
"github.com/skip-mev/slinky/abci/strategies/aggregator"
compression "github.com/skip-mev/slinky/abci/strategies/codec"
"github.com/skip-mev/slinky/abci/strategies/currencypair"
"github.com/skip-mev/slinky/abci/ve"
oracleconfig "github.com/skip-mev/slinky/oracle/config"
"github.com/skip-mev/slinky/pkg/math/voteweighted"
oracleclient "github.com/skip-mev/slinky/service/clients/oracle"
servicemetrics "github.com/skip-mev/slinky/service/metrics"
promserver "github.com/skip-mev/slinky/service/servers/prometheus"

// Grpc Streaming
streaming "github.com/dydxprotocol/v4-chain/protocol/streaming/grpc"
Expand Down Expand Up @@ -327,11 +336,13 @@ type App struct {
PriceFeedClient *pricefeedclient.Client
LiquidationsClient *liquidationclient.Client
BridgeClient *bridgeclient.Client
SlinkyClient *slinkyclient.Client

DaemonHealthMonitor *daemonservertypes.HealthMonitor

// Slinky
SlinkyClient *slinkyclient.Client
oraclePrometheusServer *promserver.PrometheusServer
oracleMetrics servicemetrics.Metrics
}

// assertAppPreconditions assert invariants required for an application to start.
Expand Down Expand Up @@ -448,6 +459,7 @@ func New(
return nil
},
)
app.initOracleMetrics(appOpts)

app.ParamsKeeper = initParamsKeeper(appCodec, cdc, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey])

Expand Down Expand Up @@ -1359,51 +1371,10 @@ func New(
app.SetPrecommiter(app.Precommitter)
app.SetPrepareCheckStater(app.PrepareCheckStater)

// PrepareProposal setup.
priceUpdateGenerator := prices.NewDefaultPriceUpdateGenerator(app.PricesKeeper)
if appFlags.NonValidatingFullNode {
app.SetPrepareProposal(prepare.FullNodePrepareProposalHandler())
} else {
app.SetPrepareProposal(
prepare.PrepareProposalHandler(
txConfig,
app.BridgeKeeper,
app.ClobKeeper,
app.PerpetualsKeeper,
priceUpdateGenerator,
),
)
}

// ProcessProposal setup.
priceUpdateDecoder := process.NewDefaultUpdateMarketPriceTxDecoder(app.PricesKeeper, app.txConfig.TxDecoder())
if appFlags.NonValidatingFullNode {
// Note: If the command-line flag `--non-validating-full-node` is enabled, this node will use
// an implementation of `ProcessProposal` which always returns `abci.ResponseProcessProposal_ACCEPT`.
// Full-nodes do not participate in consensus, and therefore should not participate in voting / `ProcessProposal`.
app.SetProcessProposal(
process.FullNodeProcessProposalHandler(
txConfig,
app.BridgeKeeper,
app.ClobKeeper,
app.StakingKeeper,
app.PerpetualsKeeper,
priceUpdateDecoder,
),
)
} else {
app.SetProcessProposal(
process.ProcessProposalHandler(
txConfig,
app.BridgeKeeper,
app.ClobKeeper,
app.StakingKeeper,
app.PerpetualsKeeper,
app.PricesKeeper,
priceUpdateDecoder,
),
)
}
// ProposalHandler setup.
prepareProposalHandler, processProposalHandler := app.createProposalHandlers(appFlags, txConfig, appOpts)
app.SetPrepareProposal(prepareProposalHandler)
app.SetProcessProposal(processProposalHandler)

// Note that panics from out of gas errors won't get logged, since the `OutOfGasMiddleware` is added in front of this,
// so error will get handled by that middleware and subsequent middlewares won't get executed.
Expand Down Expand Up @@ -1454,27 +1425,168 @@ func New(
}

func (app *App) initSlinkySidecarClient(appOpts servertypes.AppOptions) oracleclient.OracleClient {
// Slinky setup
// Create the oracle service.
cfg, err := oracleconfig.ReadConfigFromAppOpts(appOpts)
if err != nil {
panic(err)
}
oracleMetrics, err := servicemetrics.NewMetricsFromConfig(cfg, app.ChainID())
if err != nil {
panic(err)
}
// Create the oracle service.
slinkyClient, err := oracleclient.NewClientFromConfig(
cfg,
app.Logger().With("client", "oracle"),
oracleMetrics,
app.oracleMetrics,
)
if err != nil {
panic(err)
}
return slinkyClient
}

func (app *App) createProposalHandlers(
appFlags flags.Flags,
txConfig client.TxConfig,
appOpts servertypes.AppOptions,
) (sdk.PrepareProposalHandler, sdk.ProcessProposalHandler) {
var priceUpdateDecoder process.UpdateMarketPriceTxDecoder = process.NewDefaultUpdateMarketPriceTxDecoder(
app.PricesKeeper, app.txConfig.TxDecoder())
// If the node is a NonValidatingFullNode, we don't need to run any oracle code
// Note: If the command-line flag `--non-validating-full-node` is enabled, this node will use
// an implementation of `ProcessProposal` which always returns `abci.ResponseProcessProposal_ACCEPT`.
// Full-nodes do not participate in consensus, and therefore should not participate in voting / `ProcessProposal`.
if appFlags.NonValidatingFullNode {
if app.oracleMetrics == nil {
app.oracleMetrics = servicemetrics.NewNopMetrics()
}
return prepare.FullNodePrepareProposalHandler(), process.FullNodeProcessProposalHandler(
txConfig,
app.BridgeKeeper,
app.ClobKeeper,
app.StakingKeeper,
app.PerpetualsKeeper,
priceUpdateDecoder,
)
}
strategy := currencypair.NewDefaultCurrencyPairStrategy(app.PricesKeeper)
var priceUpdateGenerator prices.PriceUpdateGenerator = prices.NewDefaultPriceUpdateGenerator(app.PricesKeeper)

veCodec := compression.NewCompressionVoteExtensionCodec(
compression.NewDefaultVoteExtensionCodec(),
compression.NewZLibCompressor(),
)
extCommitCodec := compression.NewCompressionExtendedCommitCodec(
compression.NewDefaultExtendedCommitCodec(),
compression.NewZLibCompressor(),
)

// Set Price Update Generators/Decoders for Slinky
if appFlags.VEOracleEnabled {
priceUpdateGenerator = prices.NewSlinkyPriceUpdateGenerator(
aggregator.NewDefaultVoteAggregator(
app.Logger(),
voteweighted.MedianFromContext(
app.Logger(),
app.StakingKeeper,
voteweighted.DefaultPowerThreshold,
),
strategy,
),
extCommitCodec,
veCodec,
strategy,
)
priceUpdateDecoder = process.NewSlinkyMarketPriceDecoder(
priceUpdateDecoder,
priceUpdateGenerator,
)
}
// Generate the dydx handlers
dydxPrepareProposalHandler := prepare.PrepareProposalHandler(
txConfig,
app.BridgeKeeper,
app.ClobKeeper,
app.PerpetualsKeeper,
priceUpdateGenerator,
)

// ProcessProposal setup.
var dydxProcessProposalHandler = process.ProcessProposalHandler(
txConfig,
app.BridgeKeeper,
app.ClobKeeper,
app.StakingKeeper,
app.PerpetualsKeeper,
app.PricesKeeper,
priceUpdateDecoder,
)

// Wrap dydx handlers with slinky handlers
if appFlags.VEOracleEnabled {
app.initOracle(priceUpdateDecoder)
proposalHandler := slinkyproposals.NewProposalHandler(
app.Logger(),
dydxPrepareProposalHandler,
dydxProcessProposalHandler,
ve.NewDefaultValidateVoteExtensionsFn(app.ChainID(), app.StakingKeeper),
veCodec,
extCommitCodec,
strategy,
app.oracleMetrics,
slinkyproposals.RetainOracleDataInWrappedProposalHandler(),
)
return proposalHandler.PrepareProposalHandler(), proposalHandler.ProcessProposalHandler()
}
return dydxPrepareProposalHandler, dydxProcessProposalHandler
}

func (app *App) initOracle(pricesTxDecoder process.UpdateMarketPriceTxDecoder) {
// Vote Extension setup.
slinkyVoteExtensionsHandler := ve.NewVoteExtensionHandler(
app.Logger(),
vote_extensions.NewOraclePrices(app.PricesKeeper),
time.Second,
currencypair.NewDefaultCurrencyPairStrategy(app.PricesKeeper),
compression.NewCompressionVoteExtensionCodec(
compression.NewDefaultVoteExtensionCodec(),
compression.NewZLibCompressor(),
),
app.PreBlocker,
app.oracleMetrics,
)

dydxExtendVoteHandler := vote_extensions.ExtendVoteHandler{
SlinkyExtendVoteHandler: slinkyVoteExtensionsHandler.ExtendVoteHandler(),
PricesTxDecoder: pricesTxDecoder,
PricesKeeper: app.PricesKeeper,
}

app.SetExtendVoteHandler(dydxExtendVoteHandler.ExtendVoteHandler())
app.SetVerifyVoteExtensionHandler(slinkyVoteExtensionsHandler.VerifyVoteExtensionHandler())
}

func (app *App) initOracleMetrics(appOpts servertypes.AppOptions) {
cfg, err := oracleconfig.ReadConfigFromAppOpts(appOpts)
if err != nil {
panic(err)
}
oracleMetrics, err := servicemetrics.NewMetricsFromConfig(cfg, app.ChainID())
if err != nil {
panic(err)
}
// run prometheus metrics
if cfg.MetricsEnabled {
promLogger, err := zap.NewProduction()
if err != nil {
panic(err)
}
app.oraclePrometheusServer, err = promserver.NewPrometheusServer(cfg.PrometheusServerAddress, promLogger)
if err != nil {
panic(err)
}
// start the prometheus server
go app.oraclePrometheusServer.Start()
}
app.oracleMetrics = oracleMetrics
}

// RegisterDaemonWithHealthMonitor registers a daemon service with the update monitor, which will commence monitoring
// the health of the daemon. If the daemon does not register, the method will panic.
func (app *App) RegisterDaemonWithHealthMonitor(
Expand Down Expand Up @@ -1749,6 +1861,9 @@ func (app *App) setAnteHandler(txConfig client.TxConfig) {
// Close invokes an ordered shutdown of routines.
func (app *App) Close() error {
app.BaseApp.Close()
if app.oraclePrometheusServer != nil {
app.oraclePrometheusServer.Close()
}
return app.closeOnce()
}

Expand Down
1 change: 1 addition & 0 deletions protocol/app/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ func TestAppIsFullyInitialized(t *testing.T) {
"LiquidationsClient",
"BridgeClient",
"SlinkyClient",
"oraclePrometheusServer",

// Any default constructed type can be considered initialized if the default is what is
// expected. getUninitializedStructFields relies on fields being the non-default and
Expand Down
17 changes: 17 additions & 0 deletions protocol/app/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type Flags struct {

// Grpc Streaming
GrpcStreamingEnabled bool
VEOracleEnabled bool // Slinky Vote Extensions
}

// List of CLI flags.
Expand All @@ -37,6 +38,9 @@ const (

// Grpc Streaming
GrpcStreamingEnabled = "grpc-streaming-enabled"

// Slinky VEs enabled
VEOracleEnabled = "slinky-vote-extension-oracle-enabled"
)

// Default values.
Expand All @@ -47,6 +51,7 @@ const (
DefaultDdErrorTrackingFormat = false

DefaultGrpcStreamingEnabled = false
DefaultVEOracleEnabled = true
)

// AddFlagsToCmd adds flags to app initialization.
Expand Down Expand Up @@ -80,6 +85,11 @@ func AddFlagsToCmd(cmd *cobra.Command) {
DefaultGrpcStreamingEnabled,
"Whether to enable grpc streaming for full nodes",
)
cmd.Flags().Bool(
VEOracleEnabled,
DefaultVEOracleEnabled,
"Whether to run on-chain oracle via slinky vote extensions",
)
}

// Validate checks that the flags are valid.
Expand Down Expand Up @@ -119,6 +129,7 @@ func GetFlagValuesFromOptions(
GrpcEnable: true,

GrpcStreamingEnabled: DefaultGrpcStreamingEnabled,
VEOracleEnabled: true,
}

// Populate the flags if they exist.
Expand Down Expand Up @@ -164,5 +175,11 @@ func GetFlagValuesFromOptions(
}
}

if option := appOpts.Get(VEOracleEnabled); option != nil {
if v, err := cast.ToBoolE(option); err == nil {
result.VEOracleEnabled = v
}
}

return result
}
2 changes: 1 addition & 1 deletion protocol/app/prepare/full_node_prepare_proposal.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ func FullNodePrepareProposalHandler() sdk.PrepareProposalHandler {
recordErrorMetricsWithLabel(metrics.PrepareProposalTxs)

// Return an empty response if the node is running in full-node mode so that the proposal fails.
return &EmptyResponse, nil
return &abci.ResponsePrepareProposal{Txs: [][]byte{}}, nil
}
}
Loading

0 comments on commit 12e9e28

Please sign in to comment.