Skip to content

Commit

Permalink
btc staking: initial slasher routine workflow (#1)
Browse files Browse the repository at this point in the history
Co-authored-by: Filippos Malandrakis <philmln@protonmail.com>
  • Loading branch information
SebastianElvis and filippos47 committed Aug 4, 2023
1 parent 72e9e2b commit 2b5a05f
Show file tree
Hide file tree
Showing 23 changed files with 660 additions and 181 deletions.
7 changes: 5 additions & 2 deletions .circleci/config.yml
Expand Up @@ -18,6 +18,7 @@ jobs:
command: "go env"
- go/load-cache:
key: go-mod-v6-{{ checksum "go.sum" }}
- add_ssh_keys
- go/mod-download
- run:
name: Install Dependencies
Expand Down Expand Up @@ -48,13 +49,15 @@ jobs:
resource_class: large
steps:
- checkout
- add_ssh_keys
- aws-ecr/build-image:
push-image: false
dockerfile: Dockerfile
path: ./contrib/images/vigilante
path: ./
build-path: ./
tag: "$CIRCLE_SHA1,$CIRCLE_TAG"
repo: "$CIRCLE_PROJECT_REPONAME"
extra-build-args: "--secret id=sshKey,src=/home/circleci/.ssh/$DEPLOY_KEY_NAME"
- run:
name: Save Docker image to export it to workspace
command: |
Expand Down Expand Up @@ -82,7 +85,7 @@ jobs:
- aws-ecr/push-image:
registry-id: AWS_ECR_REGISTRY_ID
region: "$AWS_REGION"
repo: "$CIRCLE_PROJECT_REPONAME"
repo: "vigilante"
tag: "$CIRCLE_SHA1,$CIRCLE_TAG"

workflows:
Expand Down
15 changes: 11 additions & 4 deletions contrib/images/vigilante/Dockerfile → Dockerfile
Expand Up @@ -4,8 +4,8 @@ FROM golang:1.20-alpine AS build-env

# TARGETPLATFORM should be one of linux/amd64 or linux/arm64.
ARG TARGETPLATFORM="linux/amd64"
# Version to build. Default is the Git HEAD.
ARG VERSION="HEAD"
# Version to build. Default is empty.
ARG VERSION

# Use muslc for static libs
ARG BUILD_TAGS="muslc"
Expand All @@ -14,14 +14,21 @@ RUN apk add --no-cache --update openssh git make build-base linux-headers libc-d
pkgconfig zeromq-dev musl-dev alpine-sdk libsodium-dev \
libzmq-static libsodium-static gcc

RUN mkdir -p /root/.ssh && ssh-keyscan github.com >> /root/.ssh/known_hosts
RUN git config --global url."git@github.com:".insteadOf "https://github.com/"
ENV GOPRIVATE=github.com/babylonchain/babylon-private,github.com/babylonchain/rpc-client-private

# Build
WORKDIR /go/src/github.com/babylonchain/vigilante
# Cache dependencies
COPY go.mod go.sum /go/src/github.com/babylonchain/vigilante/
RUN go mod download
RUN --mount=type=secret,id=sshKey,target=/root/.ssh/id_rsa go mod download
# Copy the rest of the files
COPY ./ /go/src/github.com/babylonchain/vigilante/
RUN git checkout ${VERSION}
# If version is set, then checkout this version
RUN if [ -n "${VERSION}" ]; then \
git checkout -f ${VERSION}; \
fi

# Cosmwasm - Download correct libwasmvm version
RUN WASMVM_VERSION=$(go list -m github.com/CosmWasm/wasmvm | cut -d ' ' -f 2) && \
Expand Down
11 changes: 8 additions & 3 deletions Makefile
@@ -1,3 +1,4 @@
DOCKER = $(shell which docker)
MOCKS_DIR=$(CURDIR)/testutil/mocks
MOCKGEN_REPO=github.com/golang/mock/mockgen
MOCKGEN_VERSION=v1.6.0
Expand Down Expand Up @@ -38,8 +39,6 @@ $(BUILD_TARGETS): go.sum $(BUILDDIR)/
$(BUILDDIR)/:
mkdir -p $(BUILDDIR)/

.PHONY: build

test:
go test ./...

Expand All @@ -48,8 +47,14 @@ test-e2e:
go test -mod=readonly -timeout=25m -v $(PACKAGES_E2E) -count=1 --tags=e2e

build-docker:
$(MAKE) -C contrib/images vigilante
$(DOCKER) build --secret id=sshKey,src=${BBN_PRIV_DEPLOY_KEY} --tag babylonchain/vigilante -f Dockerfile \
$(shell git rev-parse --show-toplevel)

rm-docker:
$(DOCKER) rmi babylonchain/vigilante 2>/dev/null; true

mock-gen:
mkdir -p $(MOCKS_DIR)
$(MOCKGEN_CMD) -source=btcclient/interface.go -package mocks -destination $(MOCKS_DIR)/btcclient.go

.PHONY: build test test-e2e build-docker rm-docker mock-gen
5 changes: 4 additions & 1 deletion btcclient/client_block_subscriber.go
Expand Up @@ -19,7 +19,10 @@ import (
// used by vigilant reporter
func NewWithBlockSubscriber(cfg *config.BTCConfig, retrySleepTime, maxRetrySleepTime time.Duration) (*Client, error) {
client := &Client{}
params := netparams.GetBTCParams(cfg.NetParams)
params, err := netparams.GetBTCParams(cfg.NetParams)
if err != nil {
return nil, err
}
client.blockEventChan = make(chan *types.BlockEvent, 10000) // TODO: parameterise buffer size
client.Cfg = cfg
client.Params = params
Expand Down
13 changes: 11 additions & 2 deletions btcclient/client_wallet.go
@@ -1,6 +1,8 @@
package btcclient

import (
"fmt"

"github.com/btcsuite/btcd/btcjson"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/chaincfg"
Expand All @@ -18,7 +20,10 @@ import (
// a wallet is essentially a BTC client
// that connects to the btcWallet daemon
func NewWallet(cfg *config.BTCConfig) (*Client, error) {
params := netparams.GetBTCParams(cfg.NetParams)
params, err := netparams.GetBTCParams(cfg.NetParams)
if err != nil {
return nil, err
}
wallet := &Client{}
wallet.Cfg = cfg
wallet.Params = params
Expand Down Expand Up @@ -139,7 +144,11 @@ func (c *Client) GetWalletLockTime() int64 {
}

func (c *Client) GetNetParams() *chaincfg.Params {
return netparams.GetBTCParams(c.Cfg.NetParams)
net, err := netparams.GetBTCParams(c.Cfg.NetParams)
if err != nil {
panic(fmt.Errorf("failed to get BTC network params: %w", err))
}
return net
}

func (c *Client) ListUnspent() ([]btcjson.ListUnspentResult, error) {
Expand Down
1 change: 1 addition & 0 deletions btcclient/interface.go
Expand Up @@ -19,6 +19,7 @@ type BTCClient interface {
GetBlockByHash(blockHash *chainhash.Hash) (*types.IndexedBlock, *wire.MsgBlock, error)
FindTailBlocksByHeight(height uint64) ([]*types.IndexedBlock, error)
GetBlockByHeight(height uint64) (*types.IndexedBlock, *wire.MsgBlock, error)
SendRawTransaction(tx *wire.MsgTx, allowHighFees bool) (*chainhash.Hash, error)
}

type BTCWallet interface {
Expand Down
33 changes: 8 additions & 25 deletions cmd/vigilante/cmd/monitor.go
@@ -1,7 +1,6 @@
package cmd

import (
"encoding/hex"
"fmt"

bbnqccfg "github.com/babylonchain/rpc-client/config"
Expand All @@ -12,7 +11,6 @@ import (
"github.com/babylonchain/vigilante/config"
"github.com/babylonchain/vigilante/metrics"
"github.com/babylonchain/vigilante/monitor"
"github.com/babylonchain/vigilante/monitor/btcscanner"
"github.com/babylonchain/vigilante/rpcserver"
"github.com/babylonchain/vigilante/types"
)
Expand Down Expand Up @@ -46,50 +44,35 @@ func GetMonitorCmd() *cobra.Command {
panic(fmt.Errorf("failed to load config: %w", err))
}

// create BTC client and connect to BTC server
// Note that monitor needs to subscribe to new BTC blocks
btcClient, err = btcclient.NewWithBlockSubscriber(&cfg.BTC, cfg.Common.RetrySleepTime, cfg.Common.MaxRetrySleepTime)
if err != nil {
panic(fmt.Errorf("failed to open BTC client: %w", err))
}

// create Babylon query client. Note that requests from Babylon client are ad hoc
queryCfg := &bbnqccfg.BabylonQueryConfig{
RPCAddr: cfg.Babylon.RPCAddr,
Timeout: cfg.Babylon.Timeout,
}
err = queryCfg.Validate()
if err != nil {
if err := queryCfg.Validate(); err != nil {
panic(fmt.Errorf("invalid config for query client: %w", err))
}
bbnQueryClient, err = bbnqc.New(queryCfg)
if err != nil {
panic(fmt.Errorf("failed to create babylon query client: %w", err))
}

genesisInfo, err := types.GetGenesisInfoFromFile(genesisFile)
if err != nil {
panic(fmt.Errorf("failed to read genesis file: %w", err))
}
checkpointTagBytes, err := hex.DecodeString(genesisInfo.GetCheckpointTag())
// create BTC client and connect to BTC server
// Note that monitor needs to subscribe to new BTC blocks
btcClient, err = btcclient.NewWithBlockSubscriber(&cfg.BTC, cfg.Common.RetrySleepTime, cfg.Common.MaxRetrySleepTime)
if err != nil {
panic(fmt.Errorf("invalid hex checkpoint tag: %w", err))
panic(fmt.Errorf("failed to open BTC client: %w", err))
}
btcScanner, err := btcscanner.New(
&cfg.Monitor,
btcClient,
genesisInfo.GetBaseBTCHeight(),
checkpointTagBytes,
)
genesisInfo, err := types.GetGenesisInfoFromFile(genesisFile)
if err != nil {
panic(fmt.Errorf("failed to create BTC scanner: %w", err))
panic(fmt.Errorf("failed to read genesis file: %w", err))
}

// register monitor metrics
monitorMetrics := metrics.NewMonitorMetrics()

// create monitor
vigilanteMonitor, err = monitor.New(&cfg.Monitor, genesisInfo, btcScanner, bbnQueryClient, monitorMetrics)
vigilanteMonitor, err = monitor.New(&cfg.Monitor, genesisInfo, cfg.BTC.NetParams, bbnQueryClient, btcClient, monitorMetrics)
if err != nil {
panic(fmt.Errorf("failed to create vigilante monitor: %w", err))
}
Expand Down
15 changes: 13 additions & 2 deletions config/monitor.go
Expand Up @@ -2,6 +2,8 @@ package config

import (
"fmt"

"github.com/babylonchain/vigilante/types"
)

const (
Expand All @@ -28,7 +30,11 @@ type MonitorConfig struct {
// the confirmation depth to consider a BTC block as confirmed
BtcConfirmationDepth uint64 `mapstructure:"btc-confirmation-depth"`
// whether to enable liveness checker
LivenessChecker bool `mapstructure:"liveness-checker"`
EnableLivenessChecker bool `mapstructure:"enable-liveness-checker"`
// whether to enable slasher
EnableSlasher bool `mapstructure:"enable-slasher"`
// the BTC network
BTCNetParams string `mapstructure:"btcnetparams"` // should be mainnet|testnet|simnet|signet
}

func (cfg *MonitorConfig) Validate() error {
Expand All @@ -41,6 +47,9 @@ func (cfg *MonitorConfig) Validate() error {
if cfg.BtcConfirmationDepth < defaultBtcConfirmationDepth {
return fmt.Errorf("btc-confirmation-depth should not be less than %d", defaultBtcConfirmationDepth)
}
if _, ok := types.GetValidNetParams()[cfg.BTCNetParams]; !ok {
return fmt.Errorf("invalid net params")
}
return nil
}

Expand All @@ -52,6 +61,8 @@ func DefaultMonitorConfig() MonitorConfig {
LivenessCheckIntervalSeconds: defaultLivenessCheckIntervalSeconds,
BtcConfirmationDepth: defaultBtcConfirmationDepth,
MaxLiveBtcHeights: defaultMaxLiveBtcHeights,
LivenessChecker: true,
EnableLivenessChecker: true,
EnableSlasher: true,
BTCNetParams: types.BtcSimnet.String(),
}
}
10 changes: 0 additions & 10 deletions contrib/images/Makefile

This file was deleted.

0 comments on commit 2b5a05f

Please sign in to comment.