diff --git a/btcstaking-tracker/btcslasher/slasher_utils.go b/btcstaking-tracker/btcslasher/slasher_utils.go index db6a98b5..2571bd0f 100644 --- a/btcstaking-tracker/btcslasher/slasher_utils.go +++ b/btcstaking-tracker/btcslasher/slasher_utils.go @@ -3,6 +3,7 @@ package btcslasher import ( "encoding/hex" "fmt" + "math" "strings" "github.com/avast/retry-go/v4" @@ -316,6 +317,10 @@ func BuildSlashingTxWithWitness( return nil, fmt.Errorf("failed to convert covenant pks to BTC pks: %v", err) } + if d.TotalSat > math.MaxInt64 { + panic(fmt.Errorf("TotalSat %d exceeds int64 range", d.TotalSat)) + } + // get staking info stakingInfo, err := btcstaking.BuildStakingInfo( d.BtcPk.MustToBTCPK(), diff --git a/btcstaking-tracker/stakingeventwatcher/stakingeventwatcher.go b/btcstaking-tracker/stakingeventwatcher/stakingeventwatcher.go index c241da20..295e26f4 100644 --- a/btcstaking-tracker/stakingeventwatcher/stakingeventwatcher.go +++ b/btcstaking-tracker/stakingeventwatcher/stakingeventwatcher.go @@ -183,7 +183,7 @@ func (sew *StakingEventWatcher) checkBabylonDelegations(status btcstakingtypes.B addDel(delegation) } - if len(delegations) < int(sew.cfg.NewDelegationsBatchSize) { + if uint64(len(delegations)) < sew.cfg.NewDelegationsBatchSize { // we received fewer delegations than we asked for; it means went through all of them return nil } diff --git a/config/monitor.go b/config/monitor.go index aace1b77..d5a603ac 100644 --- a/config/monitor.go +++ b/config/monitor.go @@ -26,7 +26,7 @@ type MonitorConfig struct { // Max lasting BTC heights that a checkpoint is not reported before an alarm is sent MaxLiveBtcHeights uint64 `mapstructure:"max-live-btc-heights"` // the confirmation depth to consider a BTC block as confirmed - BtcConfirmationDepth uint64 `mapstructure:"btc-confirmation-depth"` + BtcConfirmationDepth uint32 `mapstructure:"btc-confirmation-depth"` // whether to enable liveness checker EnableLivenessChecker bool `mapstructure:"enable-liveness-checker"` // DatabaseConfig stores lates epoch and height used for faster bootstrap diff --git a/monitor/btcscanner/block_handler.go b/monitor/btcscanner/block_handler.go index 4f0c569c..61b200f2 100644 --- a/monitor/btcscanner/block_handler.go +++ b/monitor/btcscanner/block_handler.go @@ -3,6 +3,7 @@ package btcscanner import ( "errors" "fmt" + "math" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/chainntnfs" @@ -91,7 +92,12 @@ func (bs *BtcScanner) handleNewBlock(height int32, header *wire.BlockHeader) err // otherwise, add the block to the cache bs.unconfirmedBlockCache.Add(ib) + if bs.unconfirmedBlockCache.Size() > math.MaxInt64 { + panic(fmt.Errorf("unconfirmedBlockCache exceeds uint32")) + } + // still unconfirmed + // #nosec G115 -- performed the conversion check above if uint32(bs.unconfirmedBlockCache.Size()) <= bs.k { return nil } diff --git a/monitor/btcscanner/btc_scanner.go b/monitor/btcscanner/btc_scanner.go index 40096ebd..4a1ce6b3 100644 --- a/monitor/btcscanner/btc_scanner.go +++ b/monitor/btcscanner/btc_scanner.go @@ -78,7 +78,7 @@ func New( logger: parentLogger.With(zap.String("module", "btcscanner")).Sugar(), btcClient: btcClient, btcNotifier: btcNotifier, - k: uint32(monitorCfg.BtcConfirmationDepth), + k: monitorCfg.BtcConfirmationDepth, ckptCache: ckptCache, unconfirmedBlockCache: unconfirmedBlockCache, confirmedBlocksChan: confirmedBlocksChan, diff --git a/monitor/liveness_checker.go b/monitor/liveness_checker.go index 658aad86..1f0debb3 100644 --- a/monitor/liveness_checker.go +++ b/monitor/liveness_checker.go @@ -2,6 +2,7 @@ package monitor import ( "fmt" + "math" "time" "github.com/pkg/errors" @@ -12,6 +13,10 @@ import ( ) func (m *Monitor) runLivenessChecker() { + if m.Cfg.LivenessCheckIntervalSeconds > uint64(math.MaxInt64/time.Second) { + panic(fmt.Errorf("LivenessCheckIntervalSeconds %d exceeds int64 range when converted to time.Duration", m.Cfg.LivenessCheckIntervalSeconds)) + } + // #nosec G115 -- performed the conversion check above ticker := time.NewTicker(time.Duration(m.Cfg.LivenessCheckIntervalSeconds) * time.Second) m.logger.Infof("liveness checker is started, checking liveness every %d seconds", m.Cfg.LivenessCheckIntervalSeconds) @@ -89,7 +94,7 @@ func (m *Monitor) CheckLiveness(cr *types.CheckpointRecord) error { return fmt.Errorf("the gap %d between two BTC heights should not be negative", gap) } - if gap > int(m.Cfg.MaxLiveBtcHeights) { + if uint64(gap) > m.Cfg.MaxLiveBtcHeights { return fmt.Errorf("%w: the gap BTC height is %d, larger than the threshold %d", types.ErrLivenessAttack, gap, m.Cfg.MaxLiveBtcHeights) } diff --git a/monitor/monitor.go b/monitor/monitor.go index d9f8656c..a913396c 100644 --- a/monitor/monitor.go +++ b/monitor/monitor.go @@ -3,6 +3,7 @@ package monitor import ( "encoding/hex" "fmt" + "math" "sort" "sync" @@ -143,6 +144,9 @@ func (m *Monitor) Start(baseHeight uint32) { } else if !exists { startHeight = baseHeight } else { + if dbHeight > math.MaxUint32 { + panic(fmt.Errorf("dbHeight %d exceeds uint32 range", dbHeight)) + } startHeight = uint32(dbHeight) + 1 } diff --git a/reporter/utils.go b/reporter/utils.go index ba489424..73373f38 100644 --- a/reporter/utils.go +++ b/reporter/utils.go @@ -200,7 +200,7 @@ func (r *Reporter) matchAndSubmitCheckpoints(signer string) (int, error) { tx1Block := ckpt.Segments[0].AssocBlock tx2Block := ckpt.Segments[1].AssocBlock r.metrics.NewReportedCheckpointGaugeVec.WithLabelValues( - strconv.Itoa(int(ckpt.Epoch)), + strconv.FormatUint(ckpt.Epoch, 10), strconv.Itoa(int(tx1Block.Height)), tx1Block.Txs[ckpt.Segments[0].TxIdx].Hash().String(), tx2Block.Txs[ckpt.Segments[1].TxIdx].Hash().String(), diff --git a/rpcserver/tls.go b/rpcserver/tls.go index c7250a6b..6e9c94f2 100644 --- a/rpcserver/tls.go +++ b/rpcserver/tls.go @@ -73,7 +73,7 @@ func generateRPCKeyPair(RPCKeyFile string, RPCCertFile string, writeKey bool) (t } err = os.WriteFile(RPCKeyFile, key, 0600) if err != nil { - os.Remove(RPCCertFile) //nolint: errcheck + _ = os.Remove(RPCCertFile) //nolint: errcheck return tls.Certificate{}, err } } diff --git a/submitter/relayer/change_address.go b/submitter/relayer/change_address.go index 512ead53..1123a4db 100644 --- a/submitter/relayer/change_address.go +++ b/submitter/relayer/change_address.go @@ -3,7 +3,7 @@ package relayer import ( "errors" "github.com/btcsuite/btcd/btcutil" - "math/rand" + "math/rand/v2" ) // GetChangeAddress randomly picks one address from local addresses that have received funds @@ -35,8 +35,8 @@ func (rl *Relayer) GetChangeAddress() (btcutil.Address, error) { } if len(segwitBech32Addrs) != 0 { - return segwitBech32Addrs[rand.Intn(len(segwitBech32Addrs))], nil + return segwitBech32Addrs[(len(segwitBech32Addrs))-1], nil } - - return legacyAddrs[rand.Intn(len(legacyAddrs))], nil + // #nosec G404 -- using math/rand/v2 + return legacyAddrs[rand.IntN(len(legacyAddrs))], nil } diff --git a/submitter/relayer/relayer.go b/submitter/relayer/relayer.go index d6301eb5..87b69795 100644 --- a/submitter/relayer/relayer.go +++ b/submitter/relayer/relayer.go @@ -203,7 +203,7 @@ func (rl *Relayer) MaybeResubmitSecondCheckpointTx(ckpt *ckpttypes.RawCheckpoint // record the metrics of the resent tx2 rl.metrics.NewSubmittedCheckpointSegmentGaugeVec.WithLabelValues( - strconv.Itoa(int(ckptEpoch)), + strconv.FormatUint(ckptEpoch, 10), "1", resubmittedTx2.TxId.String(), strconv.Itoa(int(resubmittedTx2.Fee)), @@ -374,7 +374,7 @@ func (rl *Relayer) logAndRecordCheckpointMetrics(tx1, tx2 *types.BtcTxInfo, epoc // Record metrics for the first transaction rl.metrics.NewSubmittedCheckpointSegmentGaugeVec.WithLabelValues( - strconv.Itoa(int(epochNum)), + strconv.FormatUint(epochNum, 10), "0", tx1.Tx.TxHash().String(), strconv.Itoa(int(tx1.Fee)), @@ -382,7 +382,7 @@ func (rl *Relayer) logAndRecordCheckpointMetrics(tx1, tx2 *types.BtcTxInfo, epoc // Record metrics for the second transaction rl.metrics.NewSubmittedCheckpointSegmentGaugeVec.WithLabelValues( - strconv.Itoa(int(epochNum)), + strconv.FormatUint(epochNum, 10), "1", tx2.Tx.TxHash().String(), strconv.Itoa(int(tx2.Fee)), diff --git a/types/btccache.go b/types/btccache.go index 9515016d..36dae114 100644 --- a/types/btccache.go +++ b/types/btccache.go @@ -2,6 +2,7 @@ package types import ( "fmt" + "math" "sort" "sync" ) @@ -30,7 +31,7 @@ func (b *BTCCache) Init(ibs []*IndexedBlock) error { b.Lock() defer b.Unlock() - if len(ibs) > int(b.maxEntries) { + if uint64(len(ibs)) > b.maxEntries { return ErrTooManyEntries } @@ -234,5 +235,9 @@ func (b *BTCCache) Trim() { b.blocks[i] = nil } + if b.maxEntries > uint64(math.MaxInt) { + panic(fmt.Errorf("maxEntries %d exceeds int range", b.maxEntries)) + } + b.blocks = b.blocks[len(b.blocks)-int(b.maxEntries):] }