Skip to content

Commit

Permalink
merge
Browse files Browse the repository at this point in the history
  • Loading branch information
Lazar955 committed Sep 23, 2024
2 parents f3ff18a + 8f93040 commit 6277645
Show file tree
Hide file tree
Showing 57 changed files with 1,856 additions and 2,694 deletions.
22 changes: 11 additions & 11 deletions .github/workflows/publish.yml → .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,27 @@ name: docker_publish
on:
push:
branches:
- 'main'
- 'main'
tags:
- '*'
- '*'

jobs:
lint_test:
uses: babylonlabs-io/.github/.github/workflows/[email protected]
with:
go-version: '1.23'
go-lint-version: 'v1.60.2'
run-unit-tests: true
run-integration-tests: true
run-lint: true
install-dependencies-command: |
sudo apt-get update
sudo apt-get install -y libzmq3-dev
go-version: '1.23'
go-lint-version: 'v1.60.2'
run-unit-tests: true
run-integration-tests: true
run-lint: true
install-dependencies-command: |
sudo apt-get update
sudo apt-get install -y libzmq3-dev
docker_pipeline:
needs: ["lint_test"]
uses: babylonlabs-io/.github/.github/workflows/[email protected]
secrets: inherit
with:
publish: true
publish: true
10 changes: 7 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ MOCKGEN_REPO=github.com/golang/mock/mockgen
MOCKGEN_VERSION=v1.6.0
MOCKGEN_CMD=go run ${MOCKGEN_REPO}@${MOCKGEN_VERSION}
BUILDDIR ?= $(CURDIR)/build
TOOLS_DIR := tools

BABYLON_PKG := github.com/babylonlabs-io/babylon/cmd/babylond

Expand Down Expand Up @@ -49,8 +48,7 @@ test:
go test -race ./...

test-e2e:
cd $(TOOLS_DIR); go install -trimpath $(BABYLON_PKG);
go test -race -mod=readonly -timeout=25m -v $(PACKAGES_E2E) -count=1 --tags=e2e
go test -mod=readonly -failfast -timeout=15m -v $(PACKAGES_E2E) -count=1 --parallel 12 --tags=e2e

build-docker:
$(DOCKER) build --tag babylonlabs-io/vigilante -f Dockerfile \
Expand All @@ -75,3 +73,9 @@ update-changelog:
./scripts/update_changelog.sh $(sinceTag) $(upcomingTag)

.PHONY: build test test-e2e build-docker rm-docker mocks update-changelog

proto-gen:
@$(call print, "Compiling protos.")
cd ./proto; ./gen_protos_docker.sh

.PHONY: proto-gen
55 changes: 55 additions & 0 deletions btcclient/client_wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package btcclient

import (
"fmt"
notifier "github.com/lightningnetwork/lnd/chainntnfs"

"github.com/btcsuite/btcd/btcjson"
"github.com/btcsuite/btcd/btcutil"
Expand All @@ -15,6 +16,17 @@ import (
"github.com/babylonlabs-io/vigilante/netparams"
)

type TxStatus int

const (
TxNotFound TxStatus = iota
TxInMemPool
TxInChain
)
const (
txNotFoundErrMsgBitcoind = "No such mempool or blockchain transaction"
)

// NewWallet creates a new BTC wallet
// used by vigilant submitter
// a wallet is essentially a BTC client
Expand Down Expand Up @@ -121,3 +133,46 @@ func (c *Client) FundRawTransaction(tx *wire.MsgTx, opts btcjson.FundRawTransact
func (c *Client) SignRawTransactionWithWallet(tx *wire.MsgTx) (*wire.MsgTx, bool, error) {
return c.Client.SignRawTransactionWithWallet(tx)
}

func (c *Client) GetRawTransaction(txHash *chainhash.Hash) (*btcutil.Tx, error) {
return c.Client.GetRawTransaction(txHash)
}

func notifierStateToWalletState(state notifier.TxConfStatus) TxStatus {
switch state {
case notifier.TxNotFoundIndex:
return TxNotFound
case notifier.TxFoundMempool:
return TxInMemPool
case notifier.TxFoundIndex:
return TxInChain
case notifier.TxNotFoundManually:
return TxNotFound
case notifier.TxFoundManually:
return TxInChain
default:
panic(fmt.Sprintf("unknown notifier state: %s", state))
}
}

func (c *Client) getTxDetails(req notifier.ConfRequest, msg string) (*notifier.TxConfirmation, TxStatus, error) {
res, state, err := notifier.ConfDetailsFromTxIndex(c.Client, req, msg)

if err != nil {
return nil, TxNotFound, err
}

return res, notifierStateToWalletState(state), nil
}

// TxDetails Fetch info about transaction from mempool or blockchain, requires node to have enabled transaction index
func (c *Client) TxDetails(txHash *chainhash.Hash, pkScript []byte) (*notifier.TxConfirmation, TxStatus, error) {
req, err := notifier.NewConfRequest(txHash, pkScript)

if err != nil {
return nil, TxNotFound, err
}

return c.getTxDetails(req, txNotFoundErrMsgBitcoind)

}
5 changes: 4 additions & 1 deletion btcclient/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
notifier "github.com/lightningnetwork/lnd/chainntnfs"

"github.com/babylonlabs-io/vigilante/config"
"github.com/babylonlabs-io/vigilante/types"
Expand All @@ -14,7 +15,7 @@ import (
type BTCClient interface {
Stop()
WaitForShutdown()
GetBestBlock() (*chainhash.Hash, uint64, error)
GetBestBlock() (uint64, error)
GetBlockByHash(blockHash *chainhash.Hash) (*types.IndexedBlock, *wire.MsgBlock, error)
FindTailBlocksByHeight(height uint64) ([]*types.IndexedBlock, error)
GetBlockByHeight(height uint64) (*types.IndexedBlock, *wire.MsgBlock, error)
Expand All @@ -38,4 +39,6 @@ type BTCWallet interface {
GetHighUTXOAndSum() (*btcjson.ListUnspentResult, float64, error)
FundRawTransaction(tx *wire.MsgTx, opts btcjson.FundRawTransactionOpts, isWitness *bool) (*btcjson.FundRawTransactionResult, error)
SignRawTransactionWithWallet(tx *wire.MsgTx) (*wire.MsgTx, bool, error)
GetRawTransaction(txHash *chainhash.Hash) (*btcutil.Tx, error)
TxDetails(txHash *chainhash.Hash, pkScript []byte) (*notifier.TxConfirmation, TxStatus, error)
}
41 changes: 29 additions & 12 deletions btcclient/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,14 @@ import (
"github.com/babylonlabs-io/vigilante/types"
)

// GetBestBlock provides similar functionality with the btcd.rpcclient.GetBestBlock function
// We implement this, because this function is only provided by btcd.
// TODO: replace two rpc calls with only one c.GetBlockCount
func (c *Client) GetBestBlock() (*chainhash.Hash, uint64, error) {
btcLatestBlockHash, err := c.getBestBlockHashWithRetry()
// GetBestBlock returns the height of the best block
func (c *Client) GetBestBlock() (uint64, error) {
height, err := c.getBlockCountWithRetry()
if err != nil {
return nil, 0, err
return 0, err
}
btcLatestBlock, err := c.getBlockVerboseWithRetry(btcLatestBlockHash)
if err != nil {
return nil, 0, err
}
btcLatestBlockHeight := uint64(btcLatestBlock.Height)
return btcLatestBlockHash, btcLatestBlockHeight, nil

return uint64(height), nil
}

func (c *Client) GetBlockByHash(blockHash *chainhash.Hash) (*types.IndexedBlock, *wire.MsgBlock, error) {
Expand Down Expand Up @@ -213,3 +207,26 @@ func (c *Client) FindTailBlocksByHeight(baseHeight uint64) ([]*types.IndexedBloc

return c.getChainBlocks(baseHeight, tipIb)
}

func (c *Client) getBlockCountWithRetry() (int64, error) {
var (
height int64
err error
)

if err = retry.Do(func() error {
height, err = c.GetBlockCount()
if err != nil {
return err
}
return nil
},
retry.Delay(c.retrySleepTime),
retry.MaxDelay(c.maxRetrySleepTime),
retry.Attempts(c.maxRetryTimes),
); err != nil {
c.logger.Debug("failed to query get block count", zap.Error(err))
}

return height, nil
}
3 changes: 3 additions & 0 deletions btcstaking-tracker/btcslasher/bootstrapping_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ func FuzzSlasher_Bootstrapping(f *testing.F) {
datagen.AddRandomSeedsToFuzzer(f, 10)

f.Fuzz(func(t *testing.T, seed int64) {
t.Parallel()
r := rand.New(rand.NewSource(seed))
net := &chaincfg.SimNetParams
commonCfg := config.DefaultCommonConfig()
ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockBabylonQuerier := btcslasher.NewMockBabylonQueryClient(ctrl)
mockBTCClient := mocks.NewMockBTCClient(ctrl)
Expand Down Expand Up @@ -69,6 +71,7 @@ func FuzzSlasher_Bootstrapping(f *testing.F) {
commonCfg.RetrySleepTime,
commonCfg.MaxRetrySleepTime,
commonCfg.MaxRetryTimes,
config.MaxSlashingConcurrency,
slashedFPSKChan,
metrics.NewBTCStakingTrackerMetrics().SlasherMetrics,
)
Expand Down
57 changes: 32 additions & 25 deletions btcstaking-tracker/btcslasher/slasher.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"github.com/babylonlabs-io/vigilante/types"
"github.com/decred/dcrd/dcrec/secp256k1/v4"
"golang.org/x/sync/semaphore"
"sync"
"time"

Expand Down Expand Up @@ -46,6 +47,8 @@ type BTCSlasher struct {
// channel for receiving the slash result of each BTC delegation
slashResultChan chan *SlashResult

maxSlashingConcurrency int64

metrics *metrics.SlasherMetrics

startOnce sync.Once
Expand All @@ -62,23 +65,25 @@ func New(
retrySleepTime time.Duration,
maxRetrySleepTime time.Duration,
maxRetryTimes uint,
maxSlashingConcurrency uint8,
slashedFPSKChan chan *btcec.PrivateKey,
metrics *metrics.SlasherMetrics,
) (*BTCSlasher, error) {
logger := parentLogger.With(zap.String("module", "slasher")).Sugar()

return &BTCSlasher{
logger: logger,
BTCClient: btcClient,
BBNQuerier: bbnQuerier,
netParams: netParams,
retrySleepTime: retrySleepTime,
maxRetrySleepTime: maxRetrySleepTime,
maxRetryTimes: maxRetryTimes,
slashedFPSKChan: slashedFPSKChan,
slashResultChan: make(chan *SlashResult, 1000),
quit: make(chan struct{}),
metrics: metrics,
logger: logger,
BTCClient: btcClient,
BBNQuerier: bbnQuerier,
netParams: netParams,
retrySleepTime: retrySleepTime,
maxRetrySleepTime: maxRetrySleepTime,
maxRetryTimes: maxRetryTimes,
maxSlashingConcurrency: int64(maxSlashingConcurrency),
slashedFPSKChan: slashedFPSKChan,
slashResultChan: make(chan *SlashResult, 1000),
quit: make(chan struct{}),
metrics: metrics,
}, nil
}

Expand Down Expand Up @@ -251,24 +256,26 @@ func (bs *BTCSlasher) SlashFinalityProvider(extractedFpBTCSK *btcec.PrivateKey)
// Initialize a mutex protected *btcec.PrivateKey
safeExtractedFpBTCSK := types.NewPrivateKeyWithMutex(extractedFpBTCSK)

// Initialize a semaphore to control the number of concurrent operations
sem := semaphore.NewWeighted(bs.maxSlashingConcurrency)
delegations := append(activeBTCDels, unbondedBTCDels...)

// try to slash both staking and unbonding txs for each BTC delegation
// sign and submit slashing tx for each active delegation
// TODO: use semaphore to prevent spamming BTC node
for _, del := range activeBTCDels {
bs.wg.Add(1)
go func(d *bstypes.BTCDelegationResponse) {
defer bs.wg.Done()
safeExtractedFpBTCSK.UseKey(func(key *secp256k1.PrivateKey) {
bs.slashBTCDelegation(fpBTCPK, key, d)
})
}(del)
}
// sign and submit slashing tx for each unbonded delegation
// TODO: use semaphore to prevent spamming BTC node
for _, del := range unbondedBTCDels {
// sign and submit slashing tx for each active and unbonded delegation
for _, del := range delegations {
bs.wg.Add(1)
go func(d *bstypes.BTCDelegationResponse) {
defer bs.wg.Done()
ctx, cancel := bs.quitContext()
defer cancel()

// Acquire the semaphore before interacting with the BTC node
if err := sem.Acquire(ctx, 1); err != nil {
bs.logger.Errorf("failed to acquire semaphore: %v", err)
return
}
defer sem.Release(1)

safeExtractedFpBTCSK.UseKey(func(key *secp256k1.PrivateKey) {
bs.slashBTCDelegation(fpBTCPK, key, d)
})
Expand Down
3 changes: 3 additions & 0 deletions btcstaking-tracker/btcslasher/slasher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@ func FuzzSlasher(f *testing.F) {
datagen.AddRandomSeedsToFuzzer(f, 10)

f.Fuzz(func(t *testing.T, seed int64) {
t.Parallel()
r := rand.New(rand.NewSource(seed))
net := &chaincfg.SimNetParams
commonCfg := config.DefaultCommonConfig()
ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockBabylonQuerier := btcslasher.NewMockBabylonQueryClient(ctrl)
mockBTCClient := mocks.NewMockBTCClient(ctrl)
Expand Down Expand Up @@ -79,6 +81,7 @@ func FuzzSlasher(f *testing.F) {
commonCfg.RetrySleepTime,
commonCfg.MaxRetrySleepTime,
commonCfg.MaxRetryTimes,
config.MaxSlashingConcurrency,
slashedFPSKChan,
metrics.NewBTCStakingTrackerMetrics().SlasherMetrics,
)
Expand Down
1 change: 1 addition & 0 deletions btcstaking-tracker/tracker.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ func NewBTCSTakingTracker(
commonCfg.RetrySleepTime,
commonCfg.MaxRetrySleepTime,
commonCfg.MaxRetryTimes,
cfg.MaxSlashingConcurrency,
slashedFPSKChan,
metrics.SlasherMetrics,
)
Expand Down
6 changes: 6 additions & 0 deletions cmd/vigilante/cmd/submitter.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ func GetSubmitterCmd() *cobra.Command {
// register submitter metrics
submitterMetrics := metrics.NewSubmitterMetrics()

dbBackend, err := cfg.Submitter.DatabaseConfig.GetDbBackend()
if err != nil {
panic(err)
}

// create submitter
vigilantSubmitter, err := submitter.New(
&cfg.Submitter,
Expand All @@ -73,6 +78,7 @@ func GetSubmitterCmd() *cobra.Command {
cfg.Common.MaxRetrySleepTime,
cfg.Common.MaxRetryTimes,
submitterMetrics,
dbBackend,
)
if err != nil {
panic(fmt.Errorf("failed to create vigilante submitter: %w", err))
Expand Down
Loading

0 comments on commit 6277645

Please sign in to comment.