Skip to content

Commit

Permalink
Initial commit of sidecar integration
Browse files Browse the repository at this point in the history
  • Loading branch information
Eric-Warehime committed Feb 24, 2024
1 parent b33b88c commit 5cdd35f
Show file tree
Hide file tree
Showing 14 changed files with 675 additions and 125 deletions.
15 changes: 12 additions & 3 deletions protocol/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# NB: This is a digest for a multi-arch manifest list, you will want to get this by running
# `docker buildx imagetools inspect golang:1.21-alpine`
ARG GOLANG_1_21_ALPINE_DIGEST="926f7f7e1ab8509b4e91d5ec6d5916ebb45155b0c8920291ba9f361d65385806"
ARG GOLANG_1_22_ALPINE_DIGEST="8e96e6cff6a388c2f70f5f662b64120941fcd7d4b89d62fec87520323a316bd9"

# This Dockerfile is a stateless build of the `dydxprotocold` binary as a Docker container.
# It does not include any configuration, state, or genesis information.
Expand All @@ -9,7 +9,7 @@ ARG GOLANG_1_21_ALPINE_DIGEST="926f7f7e1ab8509b4e91d5ec6d5916ebb45155b0c8920291b
# Builder
# --------------------------------------------------------

FROM golang@sha256:${GOLANG_1_21_ALPINE_DIGEST} as builder
FROM golang@sha256:${GOLANG_1_22_ALPINE_DIGEST} as builder
ARG VERSION
ARG COMMIT

Expand Down Expand Up @@ -41,15 +41,24 @@ RUN --mount=type=cache,target=/root/.cache/go-build \
-o /dydxprotocol/build/ \
./...

# Build the oracle binary
WORKDIR /
RUN git clone https://github.com/skip-mev/slinky.git
WORKDIR /slinky
RUN make build

# --------------------------------------------------------
# Runner
# --------------------------------------------------------

FROM golang@sha256:${GOLANG_1_21_ALPINE_DIGEST}
FROM golang@sha256:${GOLANG_1_22_ALPINE_DIGEST}

RUN apk add --no-cache bash

COPY --from=builder /dydxprotocol/build/dydxprotocold /bin/dydxprotocold
COPY --from=builder /slinky/build/oracle /bin/slinky
COPY --from=builder /slinky/config/local/oracle.json /etc/oracle.json
COPY --from=builder /slinky/config/local/market.json /etc/market.json

ENV HOME /dydxprotocol
WORKDIR $HOME
Expand Down
85 changes: 66 additions & 19 deletions protocol/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ import (
bridgedaemontypes "github.com/dydxprotocol/v4-chain/protocol/daemons/server/types/bridge"
liquidationtypes "github.com/dydxprotocol/v4-chain/protocol/daemons/server/types/liquidations"
pricefeedtypes "github.com/dydxprotocol/v4-chain/protocol/daemons/server/types/pricefeed"
slinkyclient "github.com/dydxprotocol/v4-chain/protocol/daemons/slinky/client"
daemontypes "github.com/dydxprotocol/v4-chain/protocol/daemons/types"

// Modules
Expand Down Expand Up @@ -198,6 +199,11 @@ import (
"github.com/dydxprotocol/v4-chain/protocol/indexer"
"github.com/dydxprotocol/v4-chain/protocol/indexer/indexer_manager"
"github.com/dydxprotocol/v4-chain/protocol/indexer/msgsender"

// Slinky
oracleconfig "github.com/skip-mev/slinky/oracle/config"
oracleclient "github.com/skip-mev/slinky/service/clients/oracle"
servicemetrics "github.com/skip-mev/slinky/service/metrics"
)

var (
Expand Down Expand Up @@ -312,6 +318,9 @@ type App struct {
BridgeClient *bridgeclient.Client

DaemonHealthMonitor *daemonservertypes.HealthMonitor

// Slinky
SlinkyClient *slinkyclient.Client
}

// assertAppPreconditions assert invariants required for an application to start.
Expand Down Expand Up @@ -420,6 +429,9 @@ func New(
if app.Server != nil {
app.Server.Stop()
}
if app.SlinkyClient != nil {
app.SlinkyClient.Stop()
}
return nil
},
)
Expand Down Expand Up @@ -751,25 +763,38 @@ func New(
}()
}

// Non-validating full-nodes have no need to run the price daemon.
if !appFlags.NonValidatingFullNode && daemonFlags.Price.Enabled {
exchangeQueryConfig := configs.ReadExchangeQueryConfigFile(homePath)
// Start pricefeed client for sending prices for the pricefeed server to consume. These prices
// are retrieved via third-party APIs like Binance and then are encoded in-memory and
// periodically sent via gRPC to a shared socket with the server.
app.PriceFeedClient = pricefeedclient.StartNewClient(
// The client will use `context.Background` so that it can have a different context from
// the main application.
context.Background(),
daemonFlags,
appFlags,
logger,
&daemontypes.GrpcClientImpl{},
exchangeQueryConfig,
constants.StaticExchangeDetails,
&pricefeedclient.SubTaskRunnerImpl{},
)
app.RegisterDaemonWithHealthMonitor(app.PriceFeedClient, maxDaemonUnhealthyDuration)
// Non-validating full-nodes have no need to run the oracle.
if !appFlags.NonValidatingFullNode {
if daemonFlags.Price.Enabled {
exchangeQueryConfig := configs.ReadExchangeQueryConfigFile(homePath)
// Start pricefeed client for sending prices for the pricefeed server to consume. These prices
// are retrieved via third-party APIs like Binance and then are encoded in-memory and
// periodically sent via gRPC to a shared socket with the server.
app.PriceFeedClient = pricefeedclient.StartNewClient(
// The client will use `context.Background` so that it can have a different context from
// the main application.
context.Background(),
daemonFlags,
appFlags,
logger,
&daemontypes.GrpcClientImpl{},
exchangeQueryConfig,
constants.StaticExchangeDetails,
&pricefeedclient.SubTaskRunnerImpl{},
)
app.RegisterDaemonWithHealthMonitor(app.PriceFeedClient, maxDaemonUnhealthyDuration)
}
if daemonFlags.Slinky.Enabled {
app.SlinkyClient = slinkyclient.StartNewClient(
context.Background(),
app.initSlinkySidecarClient(appOpts),
&daemontypes.GrpcClientImpl{},
daemonFlags,
appFlags,
logger,
)
}

}

// Start Bridge Daemon.
Expand Down Expand Up @@ -1387,6 +1412,28 @@ func New(
return app
}

func (app *App) initSlinkySidecarClient(appOpts servertypes.AppOptions) oracleclient.OracleClient {
// Slinky setup
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,
)
if err != nil {
panic(err)
}
return slinkyClient
}

// 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
11 changes: 10 additions & 1 deletion protocol/cmd/dydxprotocold/cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
serverconfig "github.com/cosmos/cosmos-sdk/server/config"
assettypes "github.com/dydxprotocol/v4-chain/protocol/x/assets/types"
clobtypes "github.com/dydxprotocol/v4-chain/protocol/x/clob/types"
oracleconfig "github.com/skip-mev/slinky/oracle/config"
)

const (
Expand All @@ -25,6 +26,7 @@ const (
// DydxAppConfig specifies dYdX app specific config.
type DydxAppConfig struct {
serverconfig.Config
Oracle oracleconfig.AppConfig `mapstructure:"oracle"`
}

// TODO(DEC-1718): Audit tendermint and app config parameters for mainnet.
Expand Down Expand Up @@ -52,6 +54,13 @@ func initAppConfig() (string, *DydxAppConfig) {

appConfig := DydxAppConfig{
Config: *srvCfg,
Oracle: oracleconfig.AppConfig{
Enabled: true,
OracleAddress: "localhost:8080",
ClientTimeout: time.Second * 2,
MetricsEnabled: false,
PrometheusServerAddress: "",
},
}

// Enable telemetry.
Expand All @@ -65,7 +74,7 @@ func initAppConfig() (string, *DydxAppConfig) {
// GRPC.
appConfig.GRPC.Address = "0.0.0.0:9090"

appTemplate := serverconfig.DefaultConfigTemplate
appTemplate := serverconfig.DefaultConfigTemplate + oracleconfig.DefaultConfigTemplate

return appTemplate, &appConfig
}
Expand Down
25 changes: 25 additions & 0 deletions protocol/daemons/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ const (
FlagLiquidationDaemonEnabled = "liquidation-daemon-enabled"
FlagLiquidationDaemonLoopDelayMs = "liquidation-daemon-loop-delay-ms"
FlagLiquidationDaemonQueryPageLimit = "liquidation-daemon-query-page-limit"

FlagSlinkyDaemonEnabled = "slinky-daemon-enabled"
)

// Shared flags contains configuration flags shared by all daemons.
Expand Down Expand Up @@ -63,12 +65,18 @@ type PriceFlags struct {
LoopDelayMs uint32
}

type SlinkyFlags struct {
// Enabled toggles the slinky daemon on or off.
Enabled bool
}

// DaemonFlags contains the collected configuration flags for all daemons.
type DaemonFlags struct {
Shared SharedFlags
Bridge BridgeFlags
Liquidation LiquidationFlags
Price PriceFlags
Slinky SlinkyFlags
}

var defaultDaemonFlags *DaemonFlags
Expand Down Expand Up @@ -96,6 +104,9 @@ func GetDefaultDaemonFlags() DaemonFlags {
Enabled: true,
LoopDelayMs: 3_000,
},
Slinky: SlinkyFlags{
Enabled: false,
},
}
}
return *defaultDaemonFlags
Expand Down Expand Up @@ -173,6 +184,13 @@ func AddDaemonFlagsToCmd(
df.Price.LoopDelayMs,
"Delay in milliseconds between sending price updates to the application.",
)

// Slinky Daemon.
cmd.Flags().Bool(
FlagSlinkyDaemonEnabled,
df.Slinky.Enabled,
"Enable Slinky Daemon. Set to false for non-validator nodes.",
)
}

// GetDaemonFlagValuesFromOptions gets all daemon flag values from the `AppOptions` struct.
Expand Down Expand Up @@ -245,5 +263,12 @@ func GetDaemonFlagValuesFromOptions(
}
}

// Slinky Daemon.
if option := appOpts.Get(FlagSlinkyDaemonEnabled); option != nil {
if v, err := cast.ToBoolE(option); err == nil {
result.Slinky.Enabled = v
}
}

return result
}
Loading

0 comments on commit 5cdd35f

Please sign in to comment.