From 674853f9788ffc9c0a25d72c7a18db76f94ba21a Mon Sep 17 00:00:00 2001 From: seek Date: Wed, 11 Dec 2024 21:07:47 +0800 Subject: [PATCH 1/5] fix: panic in SendCheckpointToBTC (#138) resolve this issue: https://github.com/babylonlabs-io/vigilante/issues/137 --- CHANGELOG.md | 3 +++ submitter/submitter.go | 1 + 2 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a34d224..a892d23c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ## Unreleased +### Bug Fixes +* [#138](https://github.com/babylonlabs-io/vigilante/pull/138) fix: panic in SendCheckpointToBTC + ## v0.18.0 ### Improvements diff --git a/submitter/submitter.go b/submitter/submitter.go index d72e8fbd..e1783ffe 100644 --- a/submitter/submitter.go +++ b/submitter/submitter.go @@ -207,6 +207,7 @@ func (s *Submitter) processCheckpoints() { if err := s.relayer.SendCheckpointToBTC(ckpt); err != nil { s.logger.Errorf("Failed to submit the raw checkpoint for %v: %v", ckpt.Ckpt.EpochNum, err) s.metrics.FailedCheckpointsCounter.Inc() + continue } if err := s.relayer.MaybeResubmitSecondCheckpointTx(ckpt); err != nil { s.logger.Errorf("Failed to resubmit the raw checkpoint for %v: %v", ckpt.Ckpt.EpochNum, err) From 9ddc4fedbda73553ca7705ab6ef62498de3a6119 Mon Sep 17 00:00:00 2001 From: Lazar <12626340+Lazar955@users.noreply.github.com> Date: Wed, 11 Dec 2024 14:30:03 +0100 Subject: [PATCH 2/5] chore: add semaphore to rate limit activations (#136) Adds rate limit to number of activation go routines to less the load on RPC --- CHANGELOG.md | 5 +++++ .../stakingeventwatcher/stakingeventwatcher.go | 18 +++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a892d23c..05b7e53c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,8 +38,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ## Unreleased ### Bug Fixes + * [#138](https://github.com/babylonlabs-io/vigilante/pull/138) fix: panic in SendCheckpointToBTC +### Improvements + +* [#136](https://github.com/babylonlabs-io/vigilante/pull/136) rate limit activations + ## v0.18.0 ### Improvements diff --git a/btcstaking-tracker/stakingeventwatcher/stakingeventwatcher.go b/btcstaking-tracker/stakingeventwatcher/stakingeventwatcher.go index 613a4ab5..d16b6949 100644 --- a/btcstaking-tracker/stakingeventwatcher/stakingeventwatcher.go +++ b/btcstaking-tracker/stakingeventwatcher/stakingeventwatcher.go @@ -5,6 +5,7 @@ import ( "context" "errors" "fmt" + "golang.org/x/sync/semaphore" "sync" "sync/atomic" "time" @@ -26,8 +27,9 @@ import ( ) var ( - fixedDelyTypeWithJitter = retry.DelayType(retry.CombineDelay(retry.FixedDelay, retry.RandomDelay)) - retryForever = retry.Attempts(0) + fixedDelyTypeWithJitter = retry.DelayType(retry.CombineDelay(retry.FixedDelay, retry.RandomDelay)) + retryForever = retry.Attempts(0) + maxConcurrentActivations = int64(1000) ) func (sew *StakingEventWatcher) quitContext() (context.Context, func()) { @@ -83,6 +85,7 @@ type StakingEventWatcher struct { unbondingDelegationChan chan *newDelegation unbondingRemovalChan chan *delegationInactive currentBestBlockHeight atomic.Uint32 + activationLimiter *semaphore.Weighted } func NewStakingEventWatcher( @@ -106,6 +109,7 @@ func NewStakingEventWatcher( inProgressTracker: NewTrackedDelegations(), unbondingDelegationChan: make(chan *newDelegation), unbondingRemovalChan: make(chan *delegationInactive), + activationLimiter: semaphore.NewWeighted(maxConcurrentActivations), // todo(lazar): this should be in config } } @@ -613,6 +617,11 @@ func (sew *StakingEventWatcher) checkBtcForStakingTx() { continue } + if err := sew.activationLimiter.Acquire(context.Background(), 1); err != nil { + sew.logger.Warnf("error acquiring a activation semaphore %s", err) + continue + } + if _, err = sew.inProgressTracker.AddDelegation( del.StakingTx, del.StakingOutputIdx, @@ -624,7 +633,10 @@ func (sew *StakingEventWatcher) checkBtcForStakingTx() { continue } - go sew.activateBtcDelegation(txHash, proof, details.Block.BlockHash(), params.ConfirmationTimeBlocks) + go func() { + defer sew.activationLimiter.Release(1) + sew.activateBtcDelegation(txHash, proof, details.Block.BlockHash(), params.ConfirmationTimeBlocks) + }() } } From 5515255c2e335b39829fc7b5e28e628a7cf48114 Mon Sep 17 00:00:00 2001 From: Lazar <12626340+Lazar955@users.noreply.github.com> Date: Wed, 11 Dec 2024 15:14:49 +0100 Subject: [PATCH 3/5] chore: dec tracked delegation metric (#141) --- CHANGELOG.md | 1 + btcstaking-tracker/atomicslasher/routines.go | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05b7e53c..a6b9125f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ### Improvements * [#136](https://github.com/babylonlabs-io/vigilante/pull/136) rate limit activations +* [#141](https://github.com/babylonlabs-io/vigilante/pull/141) decrement tracked delegations in atomic slasher ## v0.18.0 diff --git a/btcstaking-tracker/atomicslasher/routines.go b/btcstaking-tracker/atomicslasher/routines.go index 0f676e50..3b34cce3 100644 --- a/btcstaking-tracker/atomicslasher/routines.go +++ b/btcstaking-tracker/atomicslasher/routines.go @@ -208,6 +208,7 @@ func (as *AtomicSlasher) selectiveSlashingReporter() { // stop tracking the delegations under this finality provider as.btcDelIndex.Remove(stakingTxHash) + as.metrics.TrackedBTCDelegationsGauge.Dec() case <-as.quit: return From fd5a57e05e2198188c3a2213ac3eddb5db6ec3e8 Mon Sep 17 00:00:00 2001 From: Lazar <12626340+Lazar955@users.noreply.github.com> Date: Wed, 11 Dec 2024 15:29:42 +0100 Subject: [PATCH 4/5] chore: housekeeping (#142) - removes unused code and scripts - a bit of housekeeping --- Makefile | 6 +-- scripts/update_changelog.sh | 77 --------------------------- types/blockevent.go | 29 ---------- types/utils.go | 2 +- utils/{channelutils.go => channel.go} | 2 +- 5 files changed, 3 insertions(+), 113 deletions(-) delete mode 100755 scripts/update_changelog.sh delete mode 100644 types/blockevent.go rename utils/{channelutils.go => channel.go} (63%) diff --git a/Makefile b/Makefile index a519fb29..a7426553 100644 --- a/Makefile +++ b/Makefile @@ -68,11 +68,7 @@ mocks: $(MOCKGEN_CMD) -source=btcstaking-tracker/atomicslasher/expected_babylon_client.go -package atomicslasher -destination btcstaking-tracker/atomicslasher/mock_babylon_client.go $(MOCKGEN_CMD) -source=btcstaking-tracker/stakingeventwatcher/expected_babylon_client.go -package stakingeventwatcher -destination btcstaking-tracker/stakingeventwatcher/mock_babylon_client.go -update-changelog: - @echo ./scripts/update_changelog.sh $(sinceTag) $(upcomingTag) - ./scripts/update_changelog.sh $(sinceTag) $(upcomingTag) - -.PHONY: build test test-e2e build-docker rm-docker mocks update-changelog +.PHONY: build test test-e2e build-docker rm-docker mocks proto-gen: @$(call print, "Compiling protos.") diff --git a/scripts/update_changelog.sh b/scripts/update_changelog.sh deleted file mode 100755 index cb35c5c1..00000000 --- a/scripts/update_changelog.sh +++ /dev/null @@ -1,77 +0,0 @@ -#!/bin/bash -# This is a wrapper around `github_changelog_generator` (https://github.com/github-changelog-generator) -# to simplify / automate updating of the CHANGELOG.md file. -# -# Originally developed for CosmWasm cw_plus (https://github.com/CosmWasm/cw-plus) repository. -set -o errexit -o pipefail - -ORIGINAL_OPTS=$* -# Requires getopt from util-linux 2.37.4 (brew install gnu-getopt on Mac) -OPTS=$(getopt -l "help,release-branch:,since-tag:,future-release:,full,token:" -o "hft" -- "$@") || exit 1 - -function print_usage() { - echo -e "Usage: $0 [-h|--help] [-f|--full] [--release-branch ] [--since-tag ] [--future-release] [-t|--token ] - --h, --help Display help. --f, --full Process changes since the beginning (by default: since latest git version tag). ---since-tag Process changes since git version tag (by default: since latest git version tag). ---future-release Put the unreleased changes in the specified . ---release-branch Limit pull requests to the release branch . ---token Pass changelog github token ." -} - -function remove_opt() { - ORIGINAL_OPTS=$(echo "$ORIGINAL_OPTS" | sed "s/\\B$1\\b//") -} - -eval set -- "$OPTS" -while true -do -case $1 in - -h|--help) - print_usage - exit 0 - ;; - --since-tag) - shift - TAG="$1" - ;; - -f|--full) - TAG="" - remove_opt $1 - ;; - --) - shift - break - ;; -esac -shift -done - -# Get user and repo from ./.git/config -ORIGIN_URL=$(git config --local remote.origin.url) -GITHUB_USER=$(echo $ORIGIN_URL | sed -n 's#.*:\([^\/]*\)\/.*#\1#p') -echo "Github user: $GITHUB_USER" -GITHUB_REPO=$(echo $ORIGIN_URL | sed -n 's#.*/\([^.]*\).*#\1#p') -echo "Github repo: $GITHUB_REPO" - -if [ -z "$TAG" ] -then - # Use latest git version tag - TAG=$(git tag --sort=creatordate | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+' | tail -1) - ORIGINAL_OPTS="$ORIGINAL_OPTS --since-tag $TAG" -fi - -echo "Git version tag: $TAG" - -touch CHANGELOG.md -cp CHANGELOG.md /tmp/CHANGELOG.md.$$ -# Consolidate tag for matching changelog entries -TAG=$(echo "$TAG" | sed -e 's/-\([A-Za-z]*\)[^A-Za-z]*/-\1/' -e 's/-$//') -echo "Consolidated tag: $TAG" -sed -i -n "/^## \\[${TAG}[^]]*\\]/,\$p" CHANGELOG.md - -echo github_changelog_generator -u $GITHUB_USER -p $GITHUB_REPO --base CHANGELOG.md $ORIGINAL_OPTS || cp /tmp/CHANGELOG.md.$$ CHANGELOG.md -github_changelog_generator -u $GITHUB_USER -p $GITHUB_REPO --base CHANGELOG.md $ORIGINAL_OPTS || cp /tmp/CHANGELOG.md.$$ CHANGELOG.md - -rm -f /tmp/CHANGELOG.md.$$ diff --git a/types/blockevent.go b/types/blockevent.go deleted file mode 100644 index a06b1c90..00000000 --- a/types/blockevent.go +++ /dev/null @@ -1,29 +0,0 @@ -package types - -import "github.com/btcsuite/btcd/wire" - -type EventType int - -const ( - // BlockDisconnected indicates the associated block was disconnected - // from the main chain. - BlockDisconnected EventType = iota - - // BlockConnected indicates the associated block was connected to the - // main chain. - BlockConnected -) - -type BlockEvent struct { - EventType EventType - Height int32 - Header *wire.BlockHeader -} - -func NewBlockEvent(eventType EventType, height int32, header *wire.BlockHeader) *BlockEvent { - return &BlockEvent{ - EventType: eventType, - Height: height, - Header: header, - } -} diff --git a/types/utils.go b/types/utils.go index bb39fd52..ca766d20 100644 --- a/types/utils.go +++ b/types/utils.go @@ -22,7 +22,7 @@ func (c SupportedBtcNetwork) String() string { } func GetWrappedTxs(msg *wire.MsgBlock) []*btcutil.Tx { - btcTxs := []*btcutil.Tx{} + btcTxs := make([]*btcutil.Tx, 0, len(msg.Transactions)) for i := range msg.Transactions { newTx := btcutil.NewTx(msg.Transactions[i]) diff --git a/utils/channelutils.go b/utils/channel.go similarity index 63% rename from utils/channelutils.go rename to utils/channel.go index a9475817..323966b1 100644 --- a/utils/channelutils.go +++ b/utils/channel.go @@ -1,6 +1,6 @@ package utils -// push msg to channel c, or quit if quit channel is closed +// PushOrQuit push msg to channel c, or quit if quit channel is closed func PushOrQuit[T any](c chan<- T, msg T, quit <-chan struct{}) { select { case c <- msg: From 242fd296993e12f0ef95975a452d30f116938ea2 Mon Sep 17 00:00:00 2001 From: Lazar <12626340+Lazar955@users.noreply.github.com> Date: Wed, 11 Dec 2024 15:56:32 +0100 Subject: [PATCH 5/5] chore: unlax linter a bit more (#143) `nlreturn` gives a more consistent code style by requiring a new line above return/continue/break statements --- .golangci.yml | 2 +- CHANGELOG.md | 1 + btcclient/client_wallet.go | 2 ++ btcclient/query.go | 11 +++++++++ .../atomicslasher/atomic_slasher.go | 3 +++ .../atomicslasher/babylon_adapter.go | 3 +++ btcstaking-tracker/atomicslasher/routines.go | 9 +++++++ btcstaking-tracker/atomicslasher/types.go | 1 + .../btcslasher/bootstrapping.go | 2 ++ btcstaking-tracker/btcslasher/btc_utils.go | 2 ++ btcstaking-tracker/btcslasher/slasher.go | 7 ++++++ btcstaking-tracker/btcslasher/slasher_test.go | 1 + .../btcslasher/slasher_utils.go | 3 +++ .../expected_babylon_client.go | 2 ++ .../stakingeventwatcher.go | 24 +++++++++++++++++++ .../tracked_delegations.go | 3 +++ btcstaking-tracker/tracker.go | 9 +++++++ cmd/vigilante/cmd/btcstaking_tracker.go | 1 + cmd/vigilante/cmd/monitor.go | 1 + cmd/vigilante/cmd/reporter.go | 1 + cmd/vigilante/cmd/submitter.go | 1 + cmd/vigilante/cmd/utils.go | 2 ++ config/common.go | 2 ++ config/dbconfig.go | 1 + config/log.go | 1 + config/monitor.go | 1 + config/reporter.go | 1 + metrics/monitor.go | 1 + metrics/reporter.go | 1 + metrics/submitter.go | 1 + monitor/btcscanner/block_handler.go | 4 ++++ monitor/btcscanner/btc_scanner.go | 5 ++++ monitor/liveness_checker.go | 1 + monitor/monitor.go | 3 +++ monitor/monitor_test.go | 1 + monitor/query.go | 9 +++++++ monitor/store/store.go | 3 +++ netparams/bitcoin.go | 1 + reporter/block_handler.go | 4 ++++ reporter/bootstrapping.go | 1 + reporter/reporter.go | 5 ++++ reporter/utils.go | 11 +++++++++ retrywrap/retry_test.go | 1 + rpcserver/tls.go | 2 ++ submitter/relayer/change_address_test.go | 1 + submitter/relayer/relayer.go | 8 +++++++ submitter/store/store.go | 1 + submitter/submitter.go | 5 ++++ testutil/datagen/reporter.go | 4 ++++ testutil/port.go | 3 +++ types/btccache.go | 3 +++ types/ckpt_bookkeeper.go | 4 +++- types/ckpt_cache.go | 3 +++ types/ckpt_cache_test.go | 1 + types/ckpt_segment.go | 1 + types/ckpt_segment_test.go | 1 + types/epoch_info.go | 2 ++ types/safeprivatekey.go | 1 + types/utxo.go | 1 + 59 files changed, 188 insertions(+), 2 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 219c7680..4b75e050 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -37,7 +37,7 @@ linters: - misspell - nakedret - nilerr -# - nlreturn # Style wise I personally like this one, todo(lazar): unlax at somepoint, good practice + - nlreturn - noctx - nonamedreturns - nosprintfhostport diff --git a/CHANGELOG.md b/CHANGELOG.md index a6b9125f..56a96239 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) * [#136](https://github.com/babylonlabs-io/vigilante/pull/136) rate limit activations * [#141](https://github.com/babylonlabs-io/vigilante/pull/141) decrement tracked delegations in atomic slasher +* [#143](https://github.com/babylonlabs-io/vigilante/pull/143) adds nlreturn linter rule ## v0.18.0 diff --git a/btcclient/client_wallet.go b/btcclient/client_wallet.go index 0645b439..e21340e6 100644 --- a/btcclient/client_wallet.go +++ b/btcclient/client_wallet.go @@ -78,6 +78,7 @@ func (c *Client) GetNetParams() *chaincfg.Params { if err != nil { panic(fmt.Errorf("failed to get BTC network params: %w", err)) } + return net } @@ -123,6 +124,7 @@ func (c *Client) GetHighUTXOAndSum() (*btcjson.ListUnspentResult, float64, error } sum += utxo.Amount } + return &highUTXO, sum, nil } diff --git a/btcclient/query.go b/btcclient/query.go index 237bf11b..efe70084 100644 --- a/btcclient/query.go +++ b/btcclient/query.go @@ -43,6 +43,7 @@ func (c *Client) GetBlockByHash(blockHash *chainhash.Hash) (*types.IndexedBlock, if height < 0 || height > int64(math.MaxUint32) { panic(fmt.Errorf("height (%d) is out of uint32 range", height)) // software bug, panic } + return types.NewIndexedBlock(uint32(height), &mBlock.Header, btcTxs), mBlock, nil } @@ -74,6 +75,7 @@ func (c *Client) getBestBlockHashWithRetry() (*chainhash.Hash, error) { if err != nil { return err } + return nil }, retry.Delay(c.retrySleepTime), @@ -82,6 +84,7 @@ func (c *Client) getBestBlockHashWithRetry() (*chainhash.Hash, error) { ); err != nil { c.logger.Debug( "failed to query the best block hash", zap.Error(err)) + return nil, err } @@ -99,6 +102,7 @@ func (c *Client) getBlockHashWithRetry(height uint32) (*chainhash.Hash, error) { if err != nil { return err } + return nil }, retry.Delay(c.retrySleepTime), @@ -107,6 +111,7 @@ func (c *Client) getBlockHashWithRetry(height uint32) (*chainhash.Hash, error) { ); err != nil { c.logger.Debug( "failed to query the block hash", zap.Uint32("height", height), zap.Error(err)) + return nil, err } @@ -124,6 +129,7 @@ func (c *Client) getBlockWithRetry(hash *chainhash.Hash) (*wire.MsgBlock, error) if err != nil { return err } + return nil }, retry.Delay(c.retrySleepTime), @@ -132,6 +138,7 @@ func (c *Client) getBlockWithRetry(hash *chainhash.Hash) (*wire.MsgBlock, error) ); err != nil { c.logger.Debug( "failed to query the block", zap.String("hash", hash.String()), zap.Error(err)) + return nil, err } @@ -149,6 +156,7 @@ func (c *Client) getBlockVerboseWithRetry(hash *chainhash.Hash) (*btcjson.GetBlo if err != nil { return err } + return nil }, retry.Delay(c.retrySleepTime), @@ -157,6 +165,7 @@ func (c *Client) getBlockVerboseWithRetry(hash *chainhash.Hash) (*btcjson.GetBlo ); err != nil { c.logger.Debug( "failed to query the block verbose", zap.String("hash", hash.String()), zap.Error(err)) + return nil, err } @@ -232,6 +241,7 @@ func (c *Client) getBlockCountWithRetry() (int64, error) { if err != nil { return err } + return nil }, retry.Delay(c.retrySleepTime), @@ -239,6 +249,7 @@ func (c *Client) getBlockCountWithRetry() (int64, error) { retry.Attempts(c.maxRetryTimes), ); err != nil { c.logger.Debug("failed to query get block count", zap.Error(err)) + return 0, err } diff --git a/btcstaking-tracker/atomicslasher/atomic_slasher.go b/btcstaking-tracker/atomicslasher/atomic_slasher.go index 95108251..e0ea55df 100644 --- a/btcstaking-tracker/atomicslasher/atomic_slasher.go +++ b/btcstaking-tracker/atomicslasher/atomic_slasher.go @@ -56,6 +56,7 @@ func New( ) *AtomicSlasher { logger := parentLogger.With(zap.String("module", "atomic_slasher")) bbnAdapter := NewBabylonAdapter(logger, cfg, retrySleepTime, maxRetrySleepTime, maxRetryTimes, bbnClient) + return &AtomicSlasher{ quit: make(chan struct{}), cfg: cfg, @@ -87,6 +88,7 @@ func (as *AtomicSlasher) Start() error { as.logger.Info("atomic slasher started") }) + return startErr } @@ -99,6 +101,7 @@ func (as *AtomicSlasher) Stop() error { as.wg.Wait() as.logger.Info("stopping atomic slasher") }) + return stopErr } diff --git a/btcstaking-tracker/atomicslasher/babylon_adapter.go b/btcstaking-tracker/atomicslasher/babylon_adapter.go index be3a73ce..273d83db 100644 --- a/btcstaking-tracker/atomicslasher/babylon_adapter.go +++ b/btcstaking-tracker/atomicslasher/babylon_adapter.go @@ -51,6 +51,7 @@ func (ba *BabylonAdapter) BTCStakingParams(ctx context.Context, version uint32) return err } bsParams = &resp.Params + return nil }, retry.Context(ctx), @@ -71,6 +72,7 @@ func (ba *BabylonAdapter) BTCDelegation(ctx context.Context, stakingTxHashHex st return err } resp = resp2 + return nil }, retry.Context(ctx), @@ -132,5 +134,6 @@ func (ba *BabylonAdapter) ReportSelectiveSlashing( // TODO: what are unrecoverable/expected errors? _, err := ba.bbnClient.ReliablySendMsg(ctx, msg, []*errors.Error{}, []*errors.Error{}) + return err } diff --git a/btcstaking-tracker/atomicslasher/routines.go b/btcstaking-tracker/atomicslasher/routines.go index 3b34cce3..40412d4a 100644 --- a/btcstaking-tracker/atomicslasher/routines.go +++ b/btcstaking-tracker/atomicslasher/routines.go @@ -27,6 +27,7 @@ func (as *AtomicSlasher) btcDelegationTracker() { } as.btcDelIndex.Add(trackedDel) as.metrics.TrackedBTCDelegationsGauge.Inc() + return nil }) if err != nil { @@ -46,6 +47,7 @@ func (as *AtomicSlasher) slashingTxTracker() { blockNotifier, err := as.btcNotifier.RegisterBlockEpochNtfn(nil) if err != nil { as.logger.Error("failed to register block notifier", zap.Error(err)) + return } defer blockNotifier.Cancel() @@ -73,6 +75,7 @@ func (as *AtomicSlasher) slashingTxTracker() { zap.String("block_hash", blockEpoch.Hash.String()), zap.Error(err), ) + continue } // filter out slashing tx / unbonding slashing tx, and @@ -115,6 +118,7 @@ func (as *AtomicSlasher) selectiveSlashingReporter() { zap.String("staking_tx_hash", stakingTxHashStr), zap.Error(err), ) + continue } // get parameter at the version of this BTC delegation @@ -128,6 +132,7 @@ func (as *AtomicSlasher) selectiveSlashingReporter() { zap.Uint32("version", paramsVersion), zap.Error(err), ) + continue } // get covenant Schnorr signature in tx @@ -143,6 +148,7 @@ func (as *AtomicSlasher) selectiveSlashingReporter() { zap.String("staking_tx_hash", stakingTxHashStr), zap.Error(err), ) + continue } @@ -156,6 +162,7 @@ func (as *AtomicSlasher) selectiveSlashingReporter() { zap.String("fp_pk", fpPK.MarshalHex()), zap.Error(err), ) + continue } cancel() @@ -166,6 +173,7 @@ func (as *AtomicSlasher) selectiveSlashingReporter() { zap.String("fp_pk", fpPK.MarshalHex()), zap.Error(err), ) + continue } @@ -186,6 +194,7 @@ func (as *AtomicSlasher) selectiveSlashingReporter() { zap.String("staking_tx_hash", stakingTxHashStr), zap.Error(err), ) + continue } diff --git a/btcstaking-tracker/atomicslasher/types.go b/btcstaking-tracker/atomicslasher/types.go index 5b3167f6..6978b3b8 100644 --- a/btcstaking-tracker/atomicslasher/types.go +++ b/btcstaking-tracker/atomicslasher/types.go @@ -190,6 +190,7 @@ func parseSlashingTxWitness( if len(fpWitnessStack[i]) != 0 { fpIdx = i fpPK = &fpPKs[i] + break } } diff --git a/btcstaking-tracker/btcslasher/bootstrapping.go b/btcstaking-tracker/btcslasher/bootstrapping.go index 4c522c49..206745d2 100644 --- a/btcstaking-tracker/btcslasher/bootstrapping.go +++ b/btcstaking-tracker/btcslasher/bootstrapping.go @@ -49,6 +49,7 @@ func (bs *BTCSlasher) Bootstrap(startHeight uint64) error { if err != nil { bs.logger.Errorf("failed to extract BTC SK of the slashed finality provider %s: %v", fpBTCPKHex, err) accumulatedErrs = multierror.Append(accumulatedErrs, err) + continue } @@ -57,6 +58,7 @@ func (bs *BTCSlasher) Bootstrap(startHeight uint64) error { if err := bs.SlashFinalityProvider(fpBTCSK); err != nil { bs.logger.Errorf("failed to slash finality provider %s: %v", fpBTCPKHex, err) accumulatedErrs = multierror.Append(accumulatedErrs, err) + continue } } diff --git a/btcstaking-tracker/btcslasher/btc_utils.go b/btcstaking-tracker/btcslasher/btc_utils.go index 676346fc..b8ac6e5f 100644 --- a/btcstaking-tracker/btcslasher/btc_utils.go +++ b/btcstaking-tracker/btcslasher/btc_utils.go @@ -12,6 +12,7 @@ import ( // TODO: ensure k-deep? func (bs *BTCSlasher) isTxSubmittedToBitcoin(txHash *chainhash.Hash) bool { _, err := bs.BTCClient.GetRawTransaction(txHash) + return err == nil } @@ -43,6 +44,7 @@ func (bs *BTCSlasher) isTaprootOutputSpendable(txBytes []byte, outIdx uint32) (b "tx %s output is already unspendable", stakingMsgTxHash.String(), ) + return false, nil } // spendable diff --git a/btcstaking-tracker/btcslasher/slasher.go b/btcstaking-tracker/btcslasher/slasher.go index 51418586..9780e16b 100644 --- a/btcstaking-tracker/btcslasher/slasher.go +++ b/btcstaking-tracker/btcslasher/slasher.go @@ -126,6 +126,7 @@ func (bs *BTCSlasher) Start() error { // load module parameters if err := bs.LoadParams(); err != nil { startErr = err + return } @@ -162,6 +163,7 @@ func (bs *BTCSlasher) slashingEnforcer() { select { case <-bs.quit: bs.logger.Debug("handle delegations loop quit") + return case fpBTCSK, ok := <-bs.slashedFPSKChan: if !ok { @@ -169,6 +171,7 @@ func (bs *BTCSlasher) slashingEnforcer() { // is out of slasher's control. So we need to ensure the channel // is not closed yet bs.logger.Debug("slashedFKSK channel is already closed, terminating the slashing enforcer") + return } // slash all the BTC delegations of this finality provider @@ -213,6 +216,7 @@ func (bs *BTCSlasher) equivocationTracker() { select { case <-bs.quit: bs.logger.Debug("handle delegations loop quit") + return case resultEvent := <-bs.finalitySigChan: evidence := filterEvidence(&resultEvent) @@ -230,6 +234,7 @@ func (bs *BTCSlasher) equivocationTracker() { fpBTCSK, err := evidence.ExtractBTCSK() if err != nil { bs.logger.Errorf("failed to extract BTC SK of the slashed finality provider %s: %v", fpBTCPKHex, err) + continue } @@ -274,6 +279,7 @@ func (bs *BTCSlasher) SlashFinalityProvider(extractedFpBTCSK *btcec.PrivateKey) // 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) @@ -309,5 +315,6 @@ func (bs *BTCSlasher) Stop() error { bs.logger.Info("stopped slasher") }) + return stopErr } diff --git a/btcstaking-tracker/btcslasher/slasher_test.go b/btcstaking-tracker/btcslasher/slasher_test.go index f555fed6..a91c3e1f 100644 --- a/btcstaking-tracker/btcslasher/slasher_test.go +++ b/btcstaking-tracker/btcslasher/slasher_test.go @@ -315,6 +315,7 @@ func newBTCDelegatorDelegationsResponse(delegations []*bstypes.BTCDelegatorDeleg delListResp = append(delListResp, bstypes.NewBTCDelegationResponse(del, status)) } } + return &bstypes.BTCDelegatorDelegationsResponse{ Dels: delListResp, } diff --git a/btcstaking-tracker/btcslasher/slasher_utils.go b/btcstaking-tracker/btcslasher/slasher_utils.go index 2538a40b..2562e7bf 100644 --- a/btcstaking-tracker/btcslasher/slasher_utils.go +++ b/btcstaking-tracker/btcslasher/slasher_utils.go @@ -292,6 +292,7 @@ func findFPIdxInWitness(fpBTCPK *bbn.BIP340PubKey, fpBtcPkList []bbn.BIP340PubKe return i, nil } } + return 0, fmt.Errorf("the given finality provider's PK is not found in the BTC delegation") } @@ -461,9 +462,11 @@ func filterEvidence(resultEvent *coretypes.ResultEvent) *ftypes.Evidence { if err := jsonpb.UnmarshalString(eventData[0], &evidence); err != nil { continue } + return &evidence } } } + return nil } diff --git a/btcstaking-tracker/stakingeventwatcher/expected_babylon_client.go b/btcstaking-tracker/stakingeventwatcher/expected_babylon_client.go index 8c157d28..e615431c 100644 --- a/btcstaking-tracker/stakingeventwatcher/expected_babylon_client.go +++ b/btcstaking-tracker/stakingeventwatcher/expected_babylon_client.go @@ -208,6 +208,7 @@ func (bca *BabylonClientAdapter) QueryHeaderDepth(headerHash *chainhash.Hash) (u return err } response = depthResponse + return nil }, retry.Attempts(5), @@ -217,6 +218,7 @@ func (bca *BabylonClientAdapter) QueryHeaderDepth(headerHash *chainhash.Hash) (u if strings.Contains(err.Error(), btclctypes.ErrHeaderDoesNotExist.Error()) { return 0, fmt.Errorf("%s: %w", err.Error(), ErrHeaderNotKnownToBabylon) } + return 0, err } diff --git a/btcstaking-tracker/stakingeventwatcher/stakingeventwatcher.go b/btcstaking-tracker/stakingeventwatcher/stakingeventwatcher.go index d16b6949..c406228e 100644 --- a/btcstaking-tracker/stakingeventwatcher/stakingeventwatcher.go +++ b/btcstaking-tracker/stakingeventwatcher/stakingeventwatcher.go @@ -121,6 +121,7 @@ func (sew *StakingEventWatcher) Start() error { blockEventNotifier, err := sew.btcNotifier.RegisterBlockEpochNtfn(nil) if err != nil { startErr = err + return } @@ -133,6 +134,7 @@ func (sew *StakingEventWatcher) Start() error { sew.currentBestBlockHeight.Store(uint32(block.Height)) case <-sew.quit: startErr = errors.New("watcher quit before finishing start") + return } @@ -146,6 +148,7 @@ func (sew *StakingEventWatcher) Start() error { sew.logger.Info("staking event watcher started") }) + return startErr } @@ -157,6 +160,7 @@ func (sew *StakingEventWatcher) Stop() error { sew.wg.Wait() sew.logger.Info("stopped staking event watcher") }) + return stopErr } @@ -293,6 +297,7 @@ func (sew *StakingEventWatcher) fetchDelegations() { wg.Wait() case <-sew.quit: sew.logger.Debug("fetch delegations loop quit") + return } } @@ -302,6 +307,7 @@ func (sew *StakingEventWatcher) syncedWithBabylon() (bool, error) { btcLightClientTipHeight, err := sew.babylonNodeAdapter.BtcClientTipHeight() if err != nil { sew.logger.Errorf("error fetching babylon tip height: %v", err) + return false, err } @@ -309,6 +315,7 @@ func (sew *StakingEventWatcher) syncedWithBabylon() (bool, error) { if currentBtcNodeHeight < btcLightClientTipHeight { sew.logger.Debugf("btc light client tip height is %d, connected node best block height is %d. Waiting for node to catch up", btcLightClientTipHeight, currentBtcNodeHeight) + return false, nil } @@ -380,15 +387,18 @@ func (sew *StakingEventWatcher) reportUnbondingToBabylon( if !active && !verified { sew.logger.Debugf("cannot report unbonding. delegation for staking tx %s is no longer active", stakingTxHash) + return nil } if err = sew.babylonNodeAdapter.ReportUnbonding(ctx, stakingTxHash, stakeSpendingTx, proof); err != nil { sew.metrics.FailedReportedUnbondingTransactions.Inc() + return fmt.Errorf("error reporting unbonding tx %s to babylon: %w", stakingTxHash, err) } sew.metrics.ReportedUnbondingTransactionsCounter.Inc() + return nil }, retry.Context(ctx), @@ -429,6 +439,7 @@ func (sew *StakingEventWatcher) watchForSpend(spendEvent *notifier.SpendEvent, t proof := sew.waitForStakeSpendInclusionProof(quitCtx, spendingTx) if proof == nil { sew.logger.Errorf("unbonding tx %s for staking tx %s proof not built", spendingTxHash, delegationID) + return } sew.reportUnbondingToBabylon(quitCtx, delegationID, spendingTx, proof) @@ -439,6 +450,7 @@ func (sew *StakingEventWatcher) watchForSpend(spendEvent *notifier.SpendEvent, t proof := sew.waitForStakeSpendInclusionProof(quitCtx, spendingTx) if proof == nil { sew.logger.Errorf("unbonding tx %s for staking tx %s proof not built", spendingTxHash, delegationID) + return } sew.logger.Debugf("found unbonding tx %s for staking tx %s", spendingTxHash, delegationID) @@ -529,6 +541,7 @@ func (sew *StakingEventWatcher) handleUnbondedDelegations() { if err != nil { sew.logger.Errorf("error adding delegation to unbondingTracker: %v", err) + continue } @@ -547,6 +560,7 @@ func (sew *StakingEventWatcher) handleUnbondedDelegations() { if err != nil { sew.logger.Errorf("error registering spend ntfn for staking tx %s: %v", activeDel.stakingTxHash, err) + continue } @@ -561,6 +575,7 @@ func (sew *StakingEventWatcher) handleUnbondedDelegations() { case <-sew.quit: sew.logger.Debug("handle delegations loop quit") + return } } @@ -578,6 +593,7 @@ func (sew *StakingEventWatcher) handlerVerifiedDelegations() { sew.checkBtcForStakingTx() case <-sew.quit: sew.logger.Debug("verified delegations loop quit") + return } } @@ -589,6 +605,7 @@ func (sew *StakingEventWatcher) checkBtcForStakingTx() { params, err := sew.babylonNodeAdapter.Params() if err != nil { sew.logger.Errorf("error getting tx params %v", err) + return } @@ -601,6 +618,7 @@ func (sew *StakingEventWatcher) checkBtcForStakingTx() { details, status, err := sew.btcClient.TxDetails(&txHash, del.StakingTx.TxOut[del.StakingOutputIdx].PkScript) if err != nil { sew.logger.Debugf("error getting tx %v", txHash) + continue } @@ -614,11 +632,13 @@ func (sew *StakingEventWatcher) checkBtcForStakingTx() { proof, err := ib.GenSPVProof(int(details.TxIndex)) if err != nil { sew.logger.Debugf("error making spv proof %s", err) + continue } if err := sew.activationLimiter.Acquire(context.Background(), 1); err != nil { sew.logger.Warnf("error acquiring a activation semaphore %s", err) + continue } @@ -630,6 +650,7 @@ func (sew *StakingEventWatcher) checkBtcForStakingTx() { false, ); err != nil { sew.logger.Warnf("add del: %s", err) + continue } @@ -668,11 +689,13 @@ func (sew *StakingEventWatcher) activateBtcDelegation( if !verified { sew.logger.Debugf("skipping tx %s is not in verified status", stakingTxHash) + return nil } if err := sew.babylonNodeAdapter.ActivateDelegation(ctx, stakingTxHash, proof); err != nil { sew.metrics.FailedReportedActivateDelegations.Inc() + return fmt.Errorf("error reporting activate delegation tx %s to babylon: %w", stakingTxHash, err) } @@ -739,6 +762,7 @@ func (sew *StakingEventWatcher) waitForRequiredDepth( func (sew *StakingEventWatcher) latency(method string) func() { startTime := time.Now() + return func() { duration := time.Since(startTime) sew.logger.Debugf("execution time for method: %s, duration: %s", method, duration.String()) diff --git a/btcstaking-tracker/stakingeventwatcher/tracked_delegations.go b/btcstaking-tracker/stakingeventwatcher/tracked_delegations.go index aad1f094..de6692e8 100644 --- a/btcstaking-tracker/stakingeventwatcher/tracked_delegations.go +++ b/btcstaking-tracker/stakingeventwatcher/tracked_delegations.go @@ -96,12 +96,15 @@ func (td *TrackedDelegations) AddDelegation( if shouldUpdate { // Update the existing delegation td.mapping[stakingTxHash] = delegation + return delegation, nil } + return nil, fmt.Errorf("delegation already tracked for staking tx hash %s", stakingTxHash) } td.mapping[stakingTxHash] = delegation + return delegation, nil } diff --git a/btcstaking-tracker/tracker.go b/btcstaking-tracker/tracker.go index a799d12f..363eac15 100644 --- a/btcstaking-tracker/tracker.go +++ b/btcstaking-tracker/tracker.go @@ -141,6 +141,7 @@ func (tracker *BTCStakingTracker) Bootstrap(startHeight uint64) error { if err := tracker.btcSlasher.Bootstrap(startHeight); err != nil { return fmt.Errorf("failed to bootstrap BTC staking tracker: %w", err) } + return nil } @@ -151,14 +152,17 @@ func (tracker *BTCStakingTracker) Start() error { if err := tracker.stakingEventWatcher.Start(); err != nil { startErr = err + return } if err := tracker.btcSlasher.Start(); err != nil { startErr = err + return } if err := tracker.atomicSlasher.Start(); err != nil { startErr = err + return } @@ -175,18 +179,22 @@ func (tracker *BTCStakingTracker) Stop() error { if err := tracker.stakingEventWatcher.Stop(); err != nil { stopErr = err + return } if err := tracker.btcSlasher.Stop(); err != nil { stopErr = err + return } if err := tracker.atomicSlasher.Stop(); err != nil { stopErr = err + return } if err := tracker.bbnClient.Stop(); err != nil { stopErr = err + return } @@ -195,5 +203,6 @@ func (tracker *BTCStakingTracker) Stop() error { tracker.logger.Info("stopped BTC staking tracker") }) + return stopErr } diff --git a/cmd/vigilante/cmd/btcstaking_tracker.go b/cmd/vigilante/cmd/btcstaking_tracker.go index dd8e6678..da1d225d 100644 --- a/cmd/vigilante/cmd/btcstaking_tracker.go +++ b/cmd/vigilante/cmd/btcstaking_tracker.go @@ -148,5 +148,6 @@ func GetBTCStakingTracker() *cobra.Command { cmd.Flags().StringVar(&babylonKeyDir, "babylon-key", "", "Directory of the Babylon key") cmd.Flags().StringVar(&cfgFile, "config", config.DefaultConfigFile(), "config file") cmd.Flags().Uint64Var(&startHeight, "start-height", 0, "height that the BTC slasher starts scanning for evidences") + return cmd } diff --git a/cmd/vigilante/cmd/monitor.go b/cmd/vigilante/cmd/monitor.go index 11f376c3..29e198e1 100644 --- a/cmd/vigilante/cmd/monitor.go +++ b/cmd/vigilante/cmd/monitor.go @@ -133,5 +133,6 @@ func GetMonitorCmd() *cobra.Command { } cmd.Flags().StringVar(&genesisFile, genesisFileNameFlag, GenesisFileNameDefault, "genesis file") cmd.Flags().StringVar(&cfgFile, "config", config.DefaultConfigFile(), "config file") + return cmd } diff --git a/cmd/vigilante/cmd/reporter.go b/cmd/vigilante/cmd/reporter.go index 02d21ed0..91a75f95 100644 --- a/cmd/vigilante/cmd/reporter.go +++ b/cmd/vigilante/cmd/reporter.go @@ -122,5 +122,6 @@ func GetReporterCmd() *cobra.Command { } cmd.Flags().StringVar(&babylonKeyDir, "babylon-key-dir", "", "Directory of the Babylon key") cmd.Flags().StringVar(&cfgFile, "config", config.DefaultConfigFile(), "config file") + return cmd } diff --git a/cmd/vigilante/cmd/submitter.go b/cmd/vigilante/cmd/submitter.go index 3c6d7986..604b9d37 100644 --- a/cmd/vigilante/cmd/submitter.go +++ b/cmd/vigilante/cmd/submitter.go @@ -119,5 +119,6 @@ func GetSubmitterCmd() *cobra.Command { }, } cmd.Flags().StringVar(&cfgFile, "config", config.DefaultConfigFile(), "config file") + return cmd } diff --git a/cmd/vigilante/cmd/utils.go b/cmd/vigilante/cmd/utils.go index d2417448..5a9085c8 100644 --- a/cmd/vigilante/cmd/utils.go +++ b/cmd/vigilante/cmd/utils.go @@ -62,10 +62,12 @@ func mainInterruptHandler() { case sig := <-interruptChannel: fmt.Printf("Received signal (%s). Shutting down...", sig) invokeCallbacks() + return case <-simulateInterruptChannel: fmt.Printf("Received shutdown request. Shutting down...") invokeCallbacks() + return case handler := <-addHandlerChannel: diff --git a/config/common.go b/config/common.go index e0435888..481afd49 100644 --- a/config/common.go +++ b/config/common.go @@ -34,6 +34,7 @@ func isOneOf(v string, list []string) bool { return true } } + return false } @@ -50,6 +51,7 @@ func (cfg *CommonConfig) Validate() error { if cfg.MaxRetrySleepTime < 0 { return errors.New("max-retry-sleep-time can't be negative") } + return nil } diff --git a/config/dbconfig.go b/config/dbconfig.go index 8b044def..af0a449a 100644 --- a/config/dbconfig.go +++ b/config/dbconfig.go @@ -75,6 +75,7 @@ func (cfg *DBConfig) Validate() error { if cfg.DBFileName == "" { return fmt.Errorf("DB file name cannot be empty") } + return nil } diff --git a/config/log.go b/config/log.go index fa6359b1..e8661e9e 100644 --- a/config/log.go +++ b/config/log.go @@ -44,6 +44,7 @@ func NewRootLogger(format string, logLevel string) (*zap.Logger, error) { case "fatal": level = zapcore.FatalLevel } + return zap.New(zapcore.NewCore( enc, os.Stderr, diff --git a/config/monitor.go b/config/monitor.go index 4332fa76..d6baabfb 100644 --- a/config/monitor.go +++ b/config/monitor.go @@ -43,6 +43,7 @@ func (cfg *MonitorConfig) Validate() error { if cfg.BtcConfirmationDepth < defaultBtcConfirmationDepth { return fmt.Errorf("btc-confirmation-depth should not be less than %d", defaultBtcConfirmationDepth) } + return nil } diff --git a/config/reporter.go b/config/reporter.go index a883a116..be3d1cee 100644 --- a/config/reporter.go +++ b/config/reporter.go @@ -28,6 +28,7 @@ func (cfg *ReporterConfig) Validate() error { if cfg.MaxHeadersInMsg < maxHeadersInMsg { return fmt.Errorf("max_headers_in_msg has to be at least %d", maxHeadersInMsg) } + return nil } diff --git a/metrics/monitor.go b/metrics/monitor.go index 5f84d18c..64406db6 100644 --- a/metrics/monitor.go +++ b/metrics/monitor.go @@ -41,5 +41,6 @@ func NewMonitorMetrics() *MonitorMetrics { Help: "The total number of detected liveness attacks", }), } + return metrics } diff --git a/metrics/reporter.go b/metrics/reporter.go index c31e76ea..51cf57cb 100644 --- a/metrics/reporter.go +++ b/metrics/reporter.go @@ -76,6 +76,7 @@ func NewReporterMetrics() *ReporterMetrics { }, ), } + return metrics } diff --git a/metrics/submitter.go b/metrics/submitter.go index 8040a2ed..1690b632 100644 --- a/metrics/submitter.go +++ b/metrics/submitter.go @@ -89,6 +89,7 @@ func NewSubmitterMetrics() *SubmitterMetrics { }), RelayerMetrics: newRelayerMetrics(registry), } + return metrics } diff --git a/monitor/btcscanner/block_handler.go b/monitor/btcscanner/block_handler.go index e9ccea42..8740e411 100644 --- a/monitor/btcscanner/block_handler.go +++ b/monitor/btcscanner/block_handler.go @@ -32,6 +32,7 @@ func (bs *BtcScanner) bootstrapAndBlockEventHandler() { blockNotifier, err := bs.btcNotifier.RegisterBlockEpochNtfn(blockEpoch) if err != nil { bs.logger.Errorf("Failed registering block epoch notifier") + return } defer blockNotifier.Cancel() @@ -40,10 +41,12 @@ func (bs *BtcScanner) bootstrapAndBlockEventHandler() { select { case <-bs.quit: bs.btcClient.Stop() + return case epoch, open := <-blockNotifier.Epochs: if !open { bs.logger.Errorf("Block event channel is closed") + return // channel closed } @@ -75,6 +78,7 @@ func (bs *BtcScanner) handleNewBlock(height uint32, header *wire.BlockHeader) er height, header.BlockHash().String(), ) + return nil } diff --git a/monitor/btcscanner/btc_scanner.go b/monitor/btcscanner/btc_scanner.go index b58bd870..53499f41 100644 --- a/monitor/btcscanner/btc_scanner.go +++ b/monitor/btcscanner/btc_scanner.go @@ -93,6 +93,7 @@ func New( func (bs *BtcScanner) Start(startHeight uint32) { if bs.started.Load() { bs.logger.Info("the BTC scanner is already started") + return } @@ -103,6 +104,7 @@ func (bs *BtcScanner) Start(startHeight uint32) { if err := bs.btcNotifier.Start(); err != nil { bs.logger.Errorf("Failed starting notifier") + return } @@ -268,11 +270,13 @@ func (bs *BtcScanner) tryToExtractCkptSegment(b *types.IndexedBlock) bool { err := bs.ckptCache.AddSegment(ckptSeg) if err != nil { bs.logger.Errorf("Failed to add the ckpt segment in tx %v to the ckptCache: %v", tx.Hash(), err) + continue } found = true } } + return found } @@ -287,6 +291,7 @@ func (bs *BtcScanner) Stop() { func (bs *BtcScanner) GetBaseHeight() uint32 { bs.mu.Lock() defer bs.mu.Unlock() + return bs.baseHeight } diff --git a/monitor/liveness_checker.go b/monitor/liveness_checker.go index 1f0debb3..c69c36fd 100644 --- a/monitor/liveness_checker.go +++ b/monitor/liveness_checker.go @@ -34,6 +34,7 @@ func (m *Monitor) runLivenessChecker() { if err != nil { m.logger.Errorf("the checkpoint at epoch %d is detected being censored: %s", c.EpochNum(), err.Error()) m.metrics.LivenessAttacksCounter.Inc() + continue } m.logger.Debugf("the checkpoint at epoch %d has passed the liveness check", c.EpochNum()) diff --git a/monitor/monitor.go b/monitor/monitor.go index b9618731..4050afc4 100644 --- a/monitor/monitor.go +++ b/monitor/monitor.go @@ -115,6 +115,7 @@ func (m *Monitor) SetLogger(logger *zap.SugaredLogger) { func (m *Monitor) Start(baseHeight uint32) { if m.started.Load() { m.logger.Info("the Monitor is already started") + return } @@ -216,6 +217,7 @@ func (m *Monitor) handleNewConfirmedCheckpoint(ckpt *types.CheckpointRecord) err } // skip the error if it is not ErrInconsistentBlockHash and verify the next BTC checkpoint m.logger.Infof("invalid BTC checkpoint found at epoch %v: %s", m.GetCurrentEpoch(), err.Error()) + return nil } @@ -276,6 +278,7 @@ func (m *Monitor) VerifyCheckpoint(btcCkpt *checkpointingtypes.RawCheckpoint) er "Babylon checkpoint's BlockHash %s, BTC checkpoint's BlockHash %s", ckpt.BlockHash.String(), btcCkpt.BlockHash) } + return nil } diff --git a/monitor/monitor_test.go b/monitor/monitor_test.go index 68f49870..5fdf871a 100644 --- a/monitor/monitor_test.go +++ b/monitor/monitor_test.go @@ -147,5 +147,6 @@ func convertToBlsPublicKeyListResponse(valBLSKeys []*ckpttypes.ValidatorWithBlsK VotingPower: valBlsKey.VotingPower, } } + return blsPublicKeyListResponse } diff --git a/monitor/query.go b/monitor/query.go index 04968ca9..75941770 100644 --- a/monitor/query.go +++ b/monitor/query.go @@ -29,6 +29,7 @@ func (m *Monitor) QueryInfoForNextEpoch(epoch uint64) (*types.EpochInfo, error) if err != nil { return nil, fmt.Errorf("failed to convert BLS key response set for epoch %v: %w", epoch, err) } + return types.NewEpochInfo(epoch, ckpttypes.ValidatorWithBlsKeySet{ValSet: blsKeys}), nil } @@ -46,6 +47,7 @@ func convertFromBlsPublicKeyListResponse(valBLSKeys []*ckpttypes.BlsPublicKeyLis VotingPower: valBlsKey.VotingPower, } } + return blsPublicKeyListResponse, nil } @@ -81,6 +83,7 @@ func (m *Monitor) queryCurrentEpochWithRetry() (*epochingtypes.QueryCurrentEpoch } currentEpochRes = *res + return nil }, retry.Delay(m.ComCfg.RetrySleepTime), @@ -106,6 +109,7 @@ func (m *Monitor) queryRawCheckpointWithRetry(epoch uint64) (*ckpttypes.QueryRaw } rawCheckpointRes = *res + return nil }, retry.Delay(m.ComCfg.RetrySleepTime), @@ -131,6 +135,7 @@ func (m *Monitor) queryBlsPublicKeyListWithRetry(epoch uint64) (*ckpttypes.Query } blsPublicKeyListRes = *res + return nil }, retry.Delay(m.ComCfg.RetrySleepTime), @@ -156,6 +161,7 @@ func (m *Monitor) queryEndedEpochBTCHeightWithRetry(epoch uint64) (*monitortypes } endedEpochBTCHeightRes = *res + return nil }, retry.Delay(m.ComCfg.RetrySleepTime), @@ -181,6 +187,7 @@ func (m *Monitor) queryReportedCheckpointBTCHeightWithRetry(hashStr string) (*mo } reportedCheckpointBtcHeightRes = *res + return nil }, retry.Delay(m.ComCfg.RetrySleepTime), @@ -206,6 +213,7 @@ func (m *Monitor) queryBTCHeaderChainTipWithRetry() (*btclctypes.QueryTipRespons } btcHeaderChainTipRes = *res + return nil }, retry.Delay(m.ComCfg.RetrySleepTime), @@ -231,6 +239,7 @@ func (m *Monitor) queryContainsBTCBlockWithRetry(blockHash *chainhash.Hash) (*bt } containsBTCBlockRes = *res + return nil }, retry.Delay(m.ComCfg.RetrySleepTime), diff --git a/monitor/store/store.go b/monitor/store/store.go index 5cd90ca4..0c468903 100644 --- a/monitor/store/store.go +++ b/monitor/store/store.go @@ -97,6 +97,7 @@ func (s *MonitorStore) get(key, bucketName []byte) (uint64, bool, error) { if errors.Is(err, ErrNotFound) { return 0, false, nil } + return 0, false, err } @@ -119,6 +120,7 @@ func uint64FromBytes(b []byte) (uint64, error) { if len(b) != 8 { return 0, fmt.Errorf("invalid byte slice length: expected 8, got %d", len(b)) } + return binary.BigEndian.Uint64(b), nil } @@ -126,5 +128,6 @@ func uint64FromBytes(b []byte) (uint64, error) { func uint64ToBytes(v uint64) []byte { var buf [8]byte binary.BigEndian.PutUint64(buf[:], v) + return buf[:] } diff --git a/netparams/bitcoin.go b/netparams/bitcoin.go index aac7d2ba..694f0ee9 100644 --- a/netparams/bitcoin.go +++ b/netparams/bitcoin.go @@ -20,6 +20,7 @@ func GetBTCParams(net string) (*chaincfg.Params, error) { case types.BtcSignet.String(): return &chaincfg.SigNetParams, nil } + return nil, fmt.Errorf( "BTC network with name %s does not exist. should be one of {%s, %s, %s, %s, %s}", net, diff --git a/reporter/block_handler.go b/reporter/block_handler.go index 19072c54..63e5fd2d 100644 --- a/reporter/block_handler.go +++ b/reporter/block_handler.go @@ -19,6 +19,7 @@ func (r *Reporter) blockEventHandler(blockNotifier *chainntnfs.BlockEpochEvent) case epoch, open := <-blockNotifier.Epochs: if !open { r.logger.Errorf("Block event channel is closed") + return // channel closed } @@ -50,6 +51,7 @@ func (r *Reporter) handleNewBlock(height uint32, header *wire.BlockHeader) error height, header.BlockHash().String(), ) + return nil } @@ -62,6 +64,7 @@ func (r *Reporter) handleNewBlock(height uint32, header *wire.BlockHeader) error if parentHash != cacheTip.BlockHash() { // If the block doesn't connect, clear the cache and bootstrap r.btcCache.RemoveAll() + return fmt.Errorf("block does not connect to the cache, diff hash, bootstrap required") } @@ -85,6 +88,7 @@ func (r *Reporter) processNewBlock(ib *types.IndexedBlock) error { if len(headersToProcess) == 0 { r.logger.Debug("No new headers to submit to Babylon") + return nil } diff --git a/reporter/bootstrapping.go b/reporter/bootstrapping.go index 6b47b66d..dfab81ad 100644 --- a/reporter/bootstrapping.go +++ b/reporter/bootstrapping.go @@ -270,6 +270,7 @@ func (r *Reporter) waitUntilBTCSync() error { bbnLatestBlockHeight = tipRes.Header.Height if btcLatestBlockHeight > 0 && btcLatestBlockHeight >= bbnLatestBlockHeight { r.logger.Infof("BTC chain (length %d) now catches up with BBN header chain (length %d), continue bootstrapping", btcLatestBlockHeight, bbnLatestBlockHeight) + break } r.logger.Infof("BTC chain (length %d) still falls behind BBN header chain (length %d), keep waiting", btcLatestBlockHeight, bbnLatestBlockHeight) diff --git a/reporter/reporter.go b/reporter/reporter.go index f2f4f866..8e3afa27 100644 --- a/reporter/reporter.go +++ b/reporter/reporter.go @@ -61,6 +61,7 @@ func New( ) err = retrywrap.Do(func() error { btccParamsRes, err = babylonClient.BTCCheckpointParams() + return err }, retry.Delay(retrySleepTime), @@ -109,6 +110,7 @@ func (r *Reporter) Start() { // Ignore when the vigilante is still running. if r.started { r.quitMu.Unlock() + return } r.started = true @@ -119,12 +121,14 @@ func (r *Reporter) Start() { if err := r.btcNotifier.Start(); err != nil { r.logger.Errorf("Failed starting notifier") + return } blockNotifier, err := r.btcNotifier.RegisterBlockEpochNtfn(nil) if err != nil { r.logger.Errorf("Failed registering block epoch notifier") + return } @@ -142,6 +146,7 @@ func (r *Reporter) quitChan() <-chan struct{} { r.quitMu.Lock() c := r.quit r.quitMu.Unlock() + return c } diff --git a/reporter/utils.go b/reporter/utils.go index 15d90300..289d4590 100644 --- a/reporter/utils.go +++ b/reporter/utils.go @@ -17,6 +17,7 @@ func chunkBy[T any](items []T, chunkSize int) [][]T { for chunkSize < len(items) { items, chunks = items[chunkSize:], append(chunks, items[0:chunkSize:chunkSize]) } + return append(chunks, items) } @@ -35,6 +36,7 @@ func (r *Reporter) getHeaderMsgsToSubmit(signer string, ibs []*types.IndexedBloc var res *btclctypes.QueryContainsBytesResponse err = retrywrap.Do(func() error { res, err = r.babylonClient.ContainsBTCBlock(&blockHash) + return err }, retry.Delay(r.retrySleepTime), @@ -45,6 +47,7 @@ func (r *Reporter) getHeaderMsgsToSubmit(signer string, ibs []*types.IndexedBloc } if !res.Contains { startPoint = i + break } } @@ -52,6 +55,7 @@ func (r *Reporter) getHeaderMsgsToSubmit(signer string, ibs []*types.IndexedBloc // all headers are duplicated, no need to submit if startPoint == -1 { r.logger.Info("All headers are duplicated, no need to submit") + return []*btclctypes.MsgInsertHeaders{}, nil } @@ -78,6 +82,7 @@ func (r *Reporter) submitHeaderMsgs(msg *btclctypes.MsgInsertHeaders) error { return err } r.logger.Infof("Successfully submitted %d headers to Babylon with response code %v", len(msg.Headers), res.Code) + return nil }, retry.Delay(r.retrySleepTime), @@ -85,6 +90,7 @@ func (r *Reporter) submitHeaderMsgs(msg *btclctypes.MsgInsertHeaders) error { ) if err != nil { r.metrics.FailedHeadersCounter.Add(float64(len(msg.Headers))) + return fmt.Errorf("failed to submit headers: %w", err) } @@ -109,6 +115,7 @@ func (r *Reporter) ProcessHeaders(signer string, ibs []*types.IndexedBlock) (int // skip if no header to submit if len(headerMsgsToSubmit) == 0 { r.logger.Info("No new headers to submit") + return 0, nil } @@ -132,6 +139,7 @@ func (r *Reporter) extractCheckpoints(ib *types.IndexedBlock) int { for _, tx := range ib.Txs { if tx == nil { r.logger.Warnf("Found a nil tx in block %v", ib.BlockHash()) + continue } @@ -141,6 +149,7 @@ func (r *Reporter) extractCheckpoints(ib *types.IndexedBlock) int { r.logger.Infof("Found a checkpoint segment in tx %v with index %d: %v", tx.Hash(), ckptSeg.Index, ckptSeg.Data) if err := r.CheckpointCache.AddSegment(ckptSeg); err != nil { r.logger.Errorf("Failed to add the ckpt segment in tx %v to the ckptCache: %v", tx.Hash(), err) + continue } numCkptSegs++ @@ -163,6 +172,7 @@ func (r *Reporter) matchAndSubmitCheckpoints(signer string) int { if numMatchedCkpts == 0 { r.logger.Debug("Found no matched pair of checkpoint segments in this match attempt") + return numMatchedCkpts } @@ -189,6 +199,7 @@ func (r *Reporter) matchAndSubmitCheckpoints(signer string) int { if err != nil { r.logger.Errorf("Failed to submit MsgInsertBTCSpvProof with error %v", err) r.metrics.FailedCheckpointsCounter.Inc() + continue } r.logger.Infof("Successfully submitted MsgInsertBTCSpvProof with response %d", res.Code) diff --git a/retrywrap/retry_test.go b/retrywrap/retry_test.go index 05fec78b..ba3ca7ae 100644 --- a/retrywrap/retry_test.go +++ b/retrywrap/retry_test.go @@ -43,6 +43,7 @@ func TestWrapDo(t *testing.T) { var attempts int retryableFunc := func() error { attempts++ + return tt.retryableErr } diff --git a/rpcserver/tls.go b/rpcserver/tls.go index 8a8a908b..3967b681 100644 --- a/rpcserver/tls.go +++ b/rpcserver/tls.go @@ -27,6 +27,7 @@ func openRPCKeyPair(oneTimeTLSKey bool, rpcKeyFile string, rpcCertFile string) ( case oneTimeTLSKey && keyExists: err := fmt.Errorf("one time TLS keys are enabled, but TLS key "+ "`%s` already exists", rpcKeyFile) + return tls.Certificate{}, err case oneTimeTLSKey: return generateRPCKeyPair(rpcKeyFile, rpcCertFile, false) @@ -74,6 +75,7 @@ func generateRPCKeyPair(rpcKeyFile string, rpcCertFile string, writeKey bool) (t err = os.WriteFile(rpcKeyFile, key, 0600) if err != nil { _ = os.Remove(rpcCertFile) //nolint: errcheck + return tls.Certificate{}, err } } diff --git a/submitter/relayer/change_address_test.go b/submitter/relayer/change_address_test.go index 4e5a768f..3ec1264b 100644 --- a/submitter/relayer/change_address_test.go +++ b/submitter/relayer/change_address_test.go @@ -97,5 +97,6 @@ func contains(s []string, e string) bool { return true } } + return false } diff --git a/submitter/relayer/relayer.go b/submitter/relayer/relayer.go index fca0665e..e5122ea3 100644 --- a/submitter/relayer/relayer.go +++ b/submitter/relayer/relayer.go @@ -69,6 +69,7 @@ func New( } metrics.ResendIntervalSecondsGauge.Set(float64(config.ResendIntervalSeconds)) + return &Relayer{ Estimator: est, BTCWallet: wallet, @@ -100,6 +101,7 @@ func (rl *Relayer) SendCheckpointToBTC(ckpt *ckpttypes.RawCheckpointWithMetaResp storeCkptFunc := func(tx1, tx2 *wire.MsgTx, epochNum uint64) error { storedCkpt := store.NewStoredCheckpoint(tx1, tx2, epochNum) + return rl.store.PutCheckpoint(storedCkpt) } @@ -161,6 +163,7 @@ func (rl *Relayer) MaybeResubmitSecondCheckpointTx(ckpt *ckpttypes.RawCheckpoint if ckpt.Status != ckpttypes.Sealed { rl.logger.Errorf("The checkpoint for epoch %v is not sealed", ckptEpoch) rl.metrics.InvalidCheckpointCounter.Inc() + return nil } @@ -170,6 +173,7 @@ func (rl *Relayer) MaybeResubmitSecondCheckpointTx(ckpt *ckpttypes.RawCheckpoint ckptEpoch, lastSubmittedEpoch) rl.metrics.InvalidCheckpointCounter.Inc() // we do not consider this case as a failed submission but a software bug + return nil } @@ -194,6 +198,7 @@ func (rl *Relayer) MaybeResubmitSecondCheckpointTx(ckpt *ckpttypes.RawCheckpoint resubmittedTx2, err := rl.resendSecondTxOfCheckpointToBTC(rl.lastSubmittedCheckpoint.Tx2, bumpedFee) if err != nil { rl.metrics.FailedResentCheckpointsCounter.Inc() + return fmt.Errorf("failed to re-send the second tx of the checkpoint %v: %w", rl.lastSubmittedCheckpoint.Epoch, err) } @@ -217,6 +222,7 @@ func (rl *Relayer) MaybeResubmitSecondCheckpointTx(ckpt *ckpttypes.RawCheckpoint rl.lastSubmittedCheckpoint.Tx2.Tx, rl.lastSubmittedCheckpoint.Epoch, ) + return rl.store.PutCheckpoint(storedCkpt) } @@ -260,6 +266,7 @@ func (rl *Relayer) resendSecondTxOfCheckpointToBTC(tx2 *types.BtcTxInfo, bumpedF // No need to resend, transaction already confirmed if status == btcclient.TxInChain { rl.logger.Debugf("Transaction %v is already confirmed", rl.lastSubmittedCheckpoint.Tx2.TxID) + return nil, nil } @@ -618,6 +625,7 @@ func (rl *Relayer) getFeeRate() chainfee.SatPerKVByte { if err != nil { defaultFee := rl.GetBTCConfig().DefaultFee rl.logger.Errorf("failed to estimate transaction fee. Using default fee %v: %s", defaultFee, err.Error()) + return defaultFee } diff --git a/submitter/store/store.go b/submitter/store/store.go index 63936ee3..4d886f28 100644 --- a/submitter/store/store.go +++ b/submitter/store/store.go @@ -126,6 +126,7 @@ func (s *SubmitterStore) get(key, bucketName []byte) ([]byte, bool, error) { if errors.Is(err, ErrNotFound) { return nil, false, nil } + return nil, false, err } diff --git a/submitter/submitter.go b/submitter/submitter.go index e1783ffe..3f23ce28 100644 --- a/submitter/submitter.go +++ b/submitter/submitter.go @@ -54,6 +54,7 @@ func New( ) err = retrywrap.Do(func() error { btccheckpointParams, err = queryClient.BTCCheckpointParams() + return err }, retry.Delay(retrySleepTime), @@ -114,6 +115,7 @@ func (s *Submitter) Start() { // Ignore when the vigilante is still running. if s.started { s.quitMu.Unlock() + return } s.started = true @@ -141,6 +143,7 @@ func (s *Submitter) quitChan() <-chan struct{} { s.quitMu.Lock() c := s.quit s.quitMu.Unlock() + return c } @@ -186,6 +189,7 @@ func (s *Submitter) pollCheckpoints() { err := s.poller.PollSealedCheckpoints() if err != nil { s.logger.Errorf("failed to query raw checkpoints: %v", err) + continue } s.logger.Debugf("Next polling happens in %v seconds", s.Cfg.PollingIntervalSeconds) @@ -207,6 +211,7 @@ func (s *Submitter) processCheckpoints() { if err := s.relayer.SendCheckpointToBTC(ckpt); err != nil { s.logger.Errorf("Failed to submit the raw checkpoint for %v: %v", ckpt.Ckpt.EpochNum, err) s.metrics.FailedCheckpointsCounter.Inc() + continue } if err := s.relayer.MaybeResubmitSecondCheckpointTx(ckpt); err != nil { diff --git a/testutil/datagen/reporter.go b/testutil/datagen/reporter.go index f627c054..ad30030f 100644 --- a/testutil/datagen/reporter.go +++ b/testutil/datagen/reporter.go @@ -30,6 +30,7 @@ func calcMerkleRoot(txns []*wire.MsgTx) chainhash.Hash { utilTxns = append(utilTxns, btcutil.NewTx(tx)) } merkles := blockchain.BuildMerkleTreeStore(utilTxns, false) + return *merkles[len(merkles)-1] } @@ -187,6 +188,7 @@ func GenRandomBlock(r *rand.Rand, numBabylonTxs int, prevHash *chainhash.Hash) ( Header: *header, Transactions: msgTxs, } + return block, rawCkpt } @@ -205,6 +207,7 @@ func GetRandomIndexedBlocks(r *rand.Rand, numBlocks uint64) []*types.IndexedBloc ibs = GetRandomIndexedBlocksFromHeight(r, numBlocks-1, prevHeight, prevHash) ibs = append([]*types.IndexedBlock{ib}, ibs...) + return ibs } @@ -267,5 +270,6 @@ func GenRandomBlockchainWithBabylonTx(r *rand.Rand, n uint64, partialPercentage blocks = append(blocks, msgBlock) rawCkpts = append(rawCkpts, rawCkpt) } + return blocks, numCkptSegs, rawCkpts } diff --git a/testutil/port.go b/testutil/port.go index 19ad7f76..fedeb7a8 100644 --- a/testutil/port.go +++ b/testutil/port.go @@ -36,12 +36,14 @@ func AllocateUniquePort(t *testing.T) int { if _, exists := allocatedPorts[port]; exists { // Port already allocated, try another one portMutex.Unlock() + continue } listener, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port)) if err != nil { portMutex.Unlock() + continue } @@ -57,5 +59,6 @@ func AllocateUniquePort(t *testing.T) int { // If no available port was found, fail the test t.Fatalf("failed to find an available port in range %d-%d", basePort, basePort+portRange) + return 0 } diff --git a/types/btccache.go b/types/btccache.go index 72c57f2b..17d7c135 100644 --- a/types/btccache.go +++ b/types/btccache.go @@ -105,6 +105,7 @@ func (b *BTCCache) RemoveLast() error { // dereference the last block to ensure it will be garbage-collected b.blocks[len(b.blocks)-1] = nil b.blocks = b.blocks[:len(b.blocks)-1] + return nil } @@ -144,6 +145,7 @@ func (b *BTCCache) GetLastBlocks(stopHeight uint32) ([]*IndexedBlock, error) { for i := len(b.blocks) - 1; i >= 0; i-- { if b.blocks[i].Height == (stopHeight) { j = i + break } } @@ -216,6 +218,7 @@ func (b *BTCCache) Resize(maxEntries uint32) error { return ErrInvalidMaxEntries } b.maxEntries = maxEntries + return nil } diff --git a/types/ckpt_bookkeeper.go b/types/ckpt_bookkeeper.go index 1b1643e1..0fe34193 100644 --- a/types/ckpt_bookkeeper.go +++ b/types/ckpt_bookkeeper.go @@ -12,7 +12,8 @@ type CheckpointsBookkeeper struct { } func NewCheckpointsBookkeeper() *CheckpointsBookkeeper { - records := make(map[string]*CheckpointRecord, 0) + records := make(map[string]*CheckpointRecord) + return &CheckpointsBookkeeper{ checkpointRecords: records, } @@ -43,6 +44,7 @@ func (cb *CheckpointsBookkeeper) Remove(id string) { func (cb *CheckpointsBookkeeper) has(id string) bool { _, exists := cb.checkpointRecords[id] + return exists } diff --git a/types/ckpt_cache.go b/types/ckpt_cache.go index 2542de28..b5e3d785 100644 --- a/types/ckpt_cache.go +++ b/types/ckpt_cache.go @@ -42,6 +42,7 @@ func (c *CheckpointCache) AddSegment(ckptSeg *CkptSegment) error { } hash := sha256.Sum256(ckptSeg.Data) c.Segments[ckptSeg.Index][string(hash[:])] = ckptSeg + return nil } @@ -89,6 +90,7 @@ func (c *CheckpointCache) PopEarliestCheckpoint() *Ckpt { if c.HasCheckpoints() { ckpt := c.Checkpoints[0] c.Checkpoints = c.Checkpoints[1:] + return ckpt } @@ -100,6 +102,7 @@ func (c *CheckpointCache) NumSegments() int { for _, segMap := range c.Segments { size += len(segMap) } + return size } diff --git a/types/ckpt_cache_test.go b/types/ckpt_cache_test.go index 5233c621..d04b8816 100644 --- a/types/ckpt_cache_test.go +++ b/types/ckpt_cache_test.go @@ -57,6 +57,7 @@ func genRandomSegments(r *rand.Rand, tag btctxformatter.BabylonTag, version btct TxIdx: r.Int(), AssocBlock: nil, } + return ckptSeg1, ckptSeg2 } diff --git a/types/ckpt_segment.go b/types/ckpt_segment.go index 1f8b19db..e2b63aa2 100644 --- a/types/ckpt_segment.go +++ b/types/ckpt_segment.go @@ -26,6 +26,7 @@ func NewCkptSegment(tag btctxformatter.BabylonTag, version btctxformatter.Format if err != nil { return nil } + return &CkptSegment{ BabylonData: bbnData, TxIdx: tx.Index(), diff --git a/types/ckpt_segment_test.go b/types/ckpt_segment_test.go index 5e5bd9f1..994dee57 100644 --- a/types/ckpt_segment_test.go +++ b/types/ckpt_segment_test.go @@ -29,6 +29,7 @@ func toWrappedTx(txHex string) (*btcutil.Tx, error) { return nil, err } wrappedTx := btcutil.NewTx(tx) + return wrappedTx, nil } diff --git a/types/epoch_info.go b/types/epoch_info.go index 7e2a6121..a602cf6c 100644 --- a/types/epoch_info.go +++ b/types/epoch_info.go @@ -56,6 +56,7 @@ func (ei *EpochInfo) Equal(epochInfo *EpochInfo) bool { return false } } + return true } @@ -73,5 +74,6 @@ func (ei *EpochInfo) VerifyMultiSig(ckpt *ckpttypes.RawCheckpoint) error { if !valid || err != nil { return ErrInvalidMultiSig } + return nil } diff --git a/types/safeprivatekey.go b/types/safeprivatekey.go index aae4222a..19e7c2a2 100644 --- a/types/safeprivatekey.go +++ b/types/safeprivatekey.go @@ -22,6 +22,7 @@ func NewPrivateKeyWithMutex(key *secp256k1.PrivateKey) *PrivateKeyWithMutex { func (p *PrivateKeyWithMutex) GetKey() *secp256k1.PrivateKey { p.mu.Lock() defer p.mu.Unlock() + return p.key } diff --git a/types/utxo.go b/types/utxo.go index 75434eff..56df2025 100644 --- a/types/utxo.go +++ b/types/utxo.go @@ -43,6 +43,7 @@ func NewUTXO(r *btcjson.ListUnspentResult, net *chaincfg.Params) (*UTXO, error) Amount: amount, Addr: prevAddr, } + return utxo, nil }