From 9a089a5eb6c8679c3e2d88563d5556bbddde98bf Mon Sep 17 00:00:00 2001 From: Lazar Date: Tue, 12 Nov 2024 17:07:21 +0100 Subject: [PATCH] batch 3 of fixes --- babylonclient/interface.go | 6 +- cmd/stakercli/transaction/transactions.go | 57 +++++------ cmd/stakerd/main.go | 6 +- itest/e2e_test.go | 2 +- metrics/prometheus.go | 1 + staker/babylontypes.go | 21 ++-- staker/commands.go | 2 +- staker/events.go | 27 +++-- staker/stakerapp.go | 118 +++++++++++----------- staker/stakercontroller.go | 8 +- staker/types.go | 7 +- stakercfg/config.go | 14 ++- stakerdb/trackedtranactionstore.go | 16 +-- stakerservice/service.go | 22 ++-- 14 files changed, 155 insertions(+), 152 deletions(-) diff --git a/babylonclient/interface.go b/babylonclient/interface.go index 588c9ec..a6ee8a9 100644 --- a/babylonclient/interface.go +++ b/babylonclient/interface.go @@ -146,16 +146,16 @@ func (m *MockBabylonClient) QueryHeaderDepth(_ *chainhash.Hash) (uint32, error) return m.ClientParams.ConfirmationTimeBlocks + 1, nil } -func (m *MockBabylonClient) IsTxAlreadyPartOfDelegation(stakingTxHash *chainhash.Hash) (bool, error) { +func (m *MockBabylonClient) IsTxAlreadyPartOfDelegation(_ *chainhash.Hash) (bool, error) { return false, nil } -func (m *MockBabylonClient) QueryDelegationInfo(stakingTxHash *chainhash.Hash) (*DelegationInfo, error) { +func (m *MockBabylonClient) QueryDelegationInfo(_ *chainhash.Hash) (*DelegationInfo, error) { return nil, fmt.Errorf("delegation do not exist") } func (m *MockBabylonClient) Undelegate( - req *UndelegationRequest) (*pv.RelayerTxResponse, error) { + _ *UndelegationRequest) (*pv.RelayerTxResponse, error) { return &pv.RelayerTxResponse{Code: 0}, nil } diff --git a/cmd/stakercli/transaction/transactions.go b/cmd/stakercli/transaction/transactions.go index b3ef85f..450e50a 100644 --- a/cmd/stakercli/transaction/transactions.go +++ b/cmd/stakercli/transaction/transactions.go @@ -954,41 +954,40 @@ func createWithdrawalInfo( withdrawalFundingUtxo: unbondingTx.TxOut[0], withdrawalSpendInfo: timeLockPathInfo, }, nil - } else { - stakingInfo, err := btcstaking.BuildStakingInfo( - parsedStakingTransaction.OpReturnData.StakerPublicKey.PubKey, - []*btcec.PublicKey{parsedStakingTransaction.OpReturnData.FinalityProviderPublicKey.PubKey}, - paramsForHeight.CovenantPks, - paramsForHeight.CovenantQuorum, - parsedStakingTransaction.OpReturnData.StakingTime, - btcutil.Amount(parsedStakingTransaction.StakingOutput.Value), - net, - ) - - if err != nil { - return nil, fmt.Errorf("error building staking info: %w", err) - } + } + stakingInfo, err := btcstaking.BuildStakingInfo( + parsedStakingTransaction.OpReturnData.StakerPublicKey.PubKey, + []*btcec.PublicKey{parsedStakingTransaction.OpReturnData.FinalityProviderPublicKey.PubKey}, + paramsForHeight.CovenantPks, + paramsForHeight.CovenantQuorum, + parsedStakingTransaction.OpReturnData.StakingTime, + btcutil.Amount(parsedStakingTransaction.StakingOutput.Value), + net, + ) - timelockPathInfo, err := stakingInfo.TimeLockPathSpendInfo() + if err != nil { + return nil, fmt.Errorf("error building staking info: %w", err) + } - if err != nil { - return nil, fmt.Errorf("error building timelock path spend info: %w", err) - } + timelockPathInfo, err := stakingInfo.TimeLockPathSpendInfo() - withdrawalOutputValue := parsedStakingTransaction.StakingOutput.Value - int64(withdrawalFee) + if err != nil { + return nil, fmt.Errorf("error building timelock path spend info: %w", err) + } - if withdrawalOutputValue <= 0 { - return nil, fmt.Errorf("too low staking output value to create withdrawal transaction. Staking amount: %d, Withdrawal fee: %d", parsedStakingTransaction.StakingOutput.Value, withdrawalFee) - } + withdrawalOutputValue := parsedStakingTransaction.StakingOutput.Value - int64(withdrawalFee) - return &withdrawalInfo{ - withdrawalOutputvalue: btcutil.Amount(withdrawalOutputValue), - withdrawalSequence: uint32(parsedStakingTransaction.OpReturnData.StakingTime), - withdrawalInput: wire.NewOutPoint(stakingTxHash, uint32(parsedStakingTransaction.StakingOutputIdx)), - withdrawalFundingUtxo: parsedStakingTransaction.StakingOutput, - withdrawalSpendInfo: timelockPathInfo, - }, nil + if withdrawalOutputValue <= 0 { + return nil, fmt.Errorf("too low staking output value to create withdrawal transaction. Staking amount: %d, Withdrawal fee: %d", parsedStakingTransaction.StakingOutput.Value, withdrawalFee) } + + return &withdrawalInfo{ + withdrawalOutputvalue: btcutil.Amount(withdrawalOutputValue), + withdrawalSequence: uint32(parsedStakingTransaction.OpReturnData.StakingTime), + withdrawalInput: wire.NewOutPoint(stakingTxHash, uint32(parsedStakingTransaction.StakingOutputIdx)), + withdrawalFundingUtxo: parsedStakingTransaction.StakingOutput, + withdrawalSpendInfo: timelockPathInfo, + }, nil } func createPhase1WitdrawalTransaction(ctx *cli.Context) error { diff --git a/cmd/stakerd/main.go b/cmd/stakerd/main.go index 1f5dbc8..64f25d0 100644 --- a/cmd/stakerd/main.go +++ b/cmd/stakerd/main.go @@ -2,6 +2,7 @@ package main import ( "context" + "errors" "fmt" "net/http" "os" @@ -25,10 +26,11 @@ func main() { cfg, cfgLogger, zapLogger, err := scfg.LoadConfig() if err != nil { - if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp { - // Print error if not due to help request. + var flagsErr *flags.Error + if !errors.As(err, &flagsErr) || flagsErr.Type != flags.ErrHelp { err = fmt.Errorf("failed to load config: %w", err) _, _ = fmt.Fprintln(os.Stderr, err) + //nolint:gocritic os.Exit(1) } diff --git a/itest/e2e_test.go b/itest/e2e_test.go index 01438ea..d446092 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -141,7 +141,7 @@ func defaultStakerConfig(t *testing.T, walletName, passphrase, bitcoindHost stri type TestManager struct { Config *stakercfg.Config Db kvdb.Backend - Sa *staker.StakerApp + Sa *staker.App BabylonClient *babylonclient.BabylonController WalletPubKey *btcec.PublicKey MinerAddr btcutil.Address diff --git a/metrics/prometheus.go b/metrics/prometheus.go index f6b157c..259d3cb 100644 --- a/metrics/prometheus.go +++ b/metrics/prometheus.go @@ -3,6 +3,7 @@ package metrics import ( "errors" "net/http" + //nolint:revive _ "net/http/pprof" "regexp" diff --git a/staker/babylontypes.go b/staker/babylontypes.go index aebe160..09579e6 100644 --- a/staker/babylontypes.go +++ b/staker/babylontypes.go @@ -34,7 +34,7 @@ type sendDelegationRequest struct { requiredInclusionBlockDepth uint32 } -func (app *StakerApp) buildOwnedDelegation( +func (app *App) buildOwnedDelegation( req *sendDelegationRequest, stakerAddress btcutil.Address, storedTx *stakerdb.StoredTransaction, @@ -133,7 +133,7 @@ func (app *StakerApp) buildOwnedDelegation( return dg, nil } -func (app *StakerApp) buildDelegation( +func (app *App) buildDelegation( req *sendDelegationRequest, stakerAddress btcutil.Address, storedTx *stakerdb.StoredTransaction) (*cl.DelegationData, error) { @@ -168,19 +168,18 @@ func (app *StakerApp) buildDelegation( &undelegationData, ) return dg, nil - } else { - return app.buildOwnedDelegation( - req, - stakerAddress, - storedTx, - ) } + return app.buildOwnedDelegation( + req, + stakerAddress, + storedTx, + ) } // TODO for now we launch this handler indefinitely. At some point we may introduce // timeout, and if signatures are not find in this timeout, then we may submit // evidence that covenant members are censoring our staking transactions -func (app *StakerApp) checkForUnbondingTxSignaturesOnBabylon(stakingTxHash *chainhash.Hash) { +func (app *App) checkForUnbondingTxSignaturesOnBabylon(stakingTxHash *chainhash.Hash) { checkSigTicker := time.NewTicker(app.config.StakerConfig.UnbondingTxCheckInterval) defer checkSigTicker.Stop() defer app.wg.Done() @@ -265,7 +264,7 @@ func (app *StakerApp) checkForUnbondingTxSignaturesOnBabylon(stakingTxHash *chai } } -func (app *StakerApp) finalityProviderExists(fpPk *btcec.PublicKey) error { +func (app *App) finalityProviderExists(fpPk *btcec.PublicKey) error { if fpPk == nil { return fmt.Errorf("provided finality provider public key is nil") } @@ -300,7 +299,7 @@ func isTransacionFullySigned(tx *wire.MsgTx) (bool, error) { // reaches verified state. i.e // - delegation is on babylon // - delegation has received enough covenant signatures -func (app *StakerApp) activateVerifiedDelegation( +func (app *App) activateVerifiedDelegation( stakingTransaction *wire.MsgTx, stakingOutputIndex uint32, stakingTxHash *chainhash.Hash) { diff --git a/staker/commands.go b/staker/commands.go index aee8b0a..5d82bfc 100644 --- a/staker/commands.go +++ b/staker/commands.go @@ -123,7 +123,7 @@ func newWatchedStakingCmd( } } -func (req *stakingRequestCmd) EventId() chainhash.Hash { +func (req *stakingRequestCmd) EventID() chainhash.Hash { // we do not have has for this event return chainhash.Hash{} } diff --git a/staker/events.go b/staker/events.go index c7b8f30..49ad6fc 100644 --- a/staker/events.go +++ b/staker/events.go @@ -8,8 +8,7 @@ import ( ) type StakingEvent interface { - // Each staking event is identified by initial staking transaction hash - EventId() chainhash.Hash + EventID() chainhash.Hash // Each staking event is identified by initial staking transaction hash EventDesc() string } @@ -32,7 +31,7 @@ type stakingTxBtcConfirmedEvent struct { inlusionBlock *wire.MsgBlock } -func (event *stakingTxBtcConfirmedEvent) EventId() chainhash.Hash { +func (event *stakingTxBtcConfirmedEvent) EventID() chainhash.Hash { return event.stakingTxHash } @@ -46,7 +45,7 @@ type delegationSubmittedToBabylonEvent struct { unbondingTime uint16 } -func (event *delegationSubmittedToBabylonEvent) EventId() chainhash.Hash { +func (event *delegationSubmittedToBabylonEvent) EventID() chainhash.Hash { return event.stakingTxHash } @@ -60,7 +59,7 @@ type unbondingTxSignaturesConfirmedOnBabylonEvent struct { covenantUnbondingSignatures []cl.CovenantSignatureInfo } -func (event *unbondingTxSignaturesConfirmedOnBabylonEvent) EventId() chainhash.Hash { +func (event *unbondingTxSignaturesConfirmedOnBabylonEvent) EventID() chainhash.Hash { return event.stakingTxHash } @@ -74,7 +73,7 @@ type unbondingTxConfirmedOnBtcEvent struct { blockHeight uint32 } -func (event *unbondingTxConfirmedOnBtcEvent) EventId() chainhash.Hash { +func (event *unbondingTxConfirmedOnBtcEvent) EventID() chainhash.Hash { return event.stakingTxHash } @@ -86,7 +85,7 @@ type spendStakeTxConfirmedOnBtcEvent struct { stakingTxHash chainhash.Hash } -func (event *spendStakeTxConfirmedOnBtcEvent) EventId() chainhash.Hash { +func (event *spendStakeTxConfirmedOnBtcEvent) EventID() chainhash.Hash { return event.stakingTxHash } @@ -100,7 +99,7 @@ type criticalErrorEvent struct { additionalContext string } -func (event *criticalErrorEvent) EventId() chainhash.Hash { +func (event *criticalErrorEvent) EventID() chainhash.Hash { return event.stakingTxHash } @@ -108,16 +107,16 @@ func (event *criticalErrorEvent) EventDesc() string { return "CRITICAL_ERROR" } -func (app *StakerApp) logStakingEventReceived(event StakingEvent) { +func (app *App) logStakingEventReceived(event StakingEvent) { app.logger.WithFields(logrus.Fields{ - "eventId": event.EventId(), + "eventId": event.EventID(), "event": event.EventDesc(), }).Debug("Received staking event") } -func (app *StakerApp) logStakingEventProcessed(event StakingEvent) { +func (app *App) logStakingEventProcessed(event StakingEvent) { app.logger.WithFields(logrus.Fields{ - "eventId": event.EventId(), + "eventId": event.EventID(), "event": event.EventDesc(), }).Debug("Processed staking event") } @@ -126,7 +125,7 @@ type delegationActivatedPostApprovalEvent struct { stakingTxHash chainhash.Hash } -func (event *delegationActivatedPostApprovalEvent) EventId() chainhash.Hash { +func (event *delegationActivatedPostApprovalEvent) EventID() chainhash.Hash { return event.stakingTxHash } @@ -140,7 +139,7 @@ type delegationActivatedPreApprovalEvent struct { blockHeight uint32 } -func (event *delegationActivatedPreApprovalEvent) EventId() chainhash.Hash { +func (event *delegationActivatedPreApprovalEvent) EventID() chainhash.Hash { return event.stakingTxHash } diff --git a/staker/stakerapp.go b/staker/stakerapp.go index 09339df..9409421 100644 --- a/staker/stakerapp.go +++ b/staker/stakerapp.go @@ -18,7 +18,6 @@ import ( "github.com/babylonlabs-io/btc-staker/types" "github.com/babylonlabs-io/btc-staker/utils" "github.com/babylonlabs-io/btc-staker/walletcontroller" - pv "github.com/cosmos/relayer/v2/relayer/provider" "go.uber.org/zap" "github.com/btcsuite/btcd/btcec/v2" @@ -70,7 +69,7 @@ func longRetryOps(ctx context.Context, fixedDelay time.Duration, onRetryFn retry } } -func (app *StakerApp) onLongRetryFunc(stakingTxHash *chainhash.Hash, msg string) retry.OnRetryFunc { +func (app *App) onLongRetryFunc(stakingTxHash *chainhash.Hash, msg string) retry.OnRetryFunc { return func(n uint, err error) { app.logger.WithFields(logrus.Fields{ "attempt": n + 1, @@ -106,7 +105,7 @@ const ( UnbondingTxConfirmations = 6 ) -type StakerApp struct { +type App struct { startOnce sync.Once stopOnce sync.Once wg sync.WaitGroup @@ -141,7 +140,7 @@ func NewStakerAppFromConfig( rpcClientLogger *zap.Logger, db kvdb.Backend, m *metrics.StakerMetrics, -) (*StakerApp, error) { +) (*App, error) { // TODO: If we want to support multiple wallet types, this is most probably the place to decide // on concrete implementation walletClient, err := walletcontroller.NewRPCWalletController(config) @@ -216,8 +215,8 @@ func NewStakerAppFromDeps( tracker *stakerdb.TrackedTransactionStore, babylonMsgSender *cl.BabylonMsgSender, metrics *metrics.StakerMetrics, -) (*StakerApp, error) { - return &StakerApp{ +) (*App, error) { + return &App{ babylonClient: cl, wc: walletClient, notifier: nodeNotifier, @@ -253,10 +252,10 @@ func NewStakerAppFromDeps( }, nil } -func (app *StakerApp) Start() error { +func (app *App) Start() error { var startErr error app.startOnce.Do(func() { - app.logger.Infof("Starting StakerApp") + app.logger.Infof("Starting App") // TODO: This can take a long time as it connects to node. Maybe make it cancellable? // although staker without node is not very useful @@ -312,13 +311,13 @@ func (app *StakerApp) Start() error { return } - app.logger.Info("StakerApp started") + app.logger.Info("App started") }) return startErr } -func (app *StakerApp) handleNewBlocks(blockNotifier *notifier.BlockEpochEvent) { +func (app *App) handleNewBlocks(blockNotifier *notifier.BlockEpochEvent) { defer app.wg.Done() defer blockNotifier.Cancel() for { @@ -340,10 +339,10 @@ func (app *StakerApp) handleNewBlocks(blockNotifier *notifier.BlockEpochEvent) { } } -func (app *StakerApp) Stop() error { +func (app *App) Stop() error { var stopErr error app.stopOnce.Do(func() { - app.logger.Infof("Stopping StakerApp") + app.logger.Infof("Stopping App") close(app.quit) app.wg.Wait() @@ -365,7 +364,7 @@ func (app *StakerApp) Stop() error { return stopErr } -func (app *StakerApp) reportCriticialError( +func (app *App) reportCriticialError( stakingTxHash chainhash.Hash, err error, additionalContext string, @@ -383,7 +382,7 @@ func (app *StakerApp) reportCriticialError( ) } -func (app *StakerApp) waitForStakingTransactionConfirmation( +func (app *App) waitForStakingTransactionConfirmation( stakingTxHash *chainhash.Hash, stakingTxPkScript []byte, requiredBlockDepth uint32, @@ -409,7 +408,7 @@ func (app *StakerApp) waitForStakingTransactionConfirmation( return nil } -func (app *StakerApp) handleBtcTxInfo( +func (app *App) handleBtcTxInfo( stakingTxHash *chainhash.Hash, txInfo *stakerdb.StoredTransaction, params *cl.StakingParams, @@ -447,7 +446,7 @@ func (app *StakerApp) handleBtcTxInfo( }).Debug("Transaction found in chain") if currentBestBlockHeight < btcTxInfo.BlockHeight { - // This is a wierd case; we retrieved transaction from btc wallet, even though wallet the best height + // This is a weird case; we retrieved transaction from btc wallet, even though wallet the best height // is lower than block height of transaction. // Log it as an error so that user can investigate. app.logger.WithFields(logrus.Fields{ @@ -504,7 +503,7 @@ func (app *StakerApp) handleBtcTxInfo( return nil } -func (app *StakerApp) mustSetTxSpentOnBtc(hash *chainhash.Hash) { +func (app *App) mustSetTxSpentOnBtc(hash *chainhash.Hash) { if err := app.txTracker.SetTxSpentOnBtc(hash); err != nil { app.logger.Fatalf("Error setting transaction spent on btc: %s", err) } @@ -513,8 +512,9 @@ func (app *StakerApp) mustSetTxSpentOnBtc(hash *chainhash.Hash) { // TODO: We should also handle case when btc node or babylon node lost data and start from scratch // i.e keep track what is last known block height on both chains and detect if after restart // for some reason they are behind staker -// TODO: Refactor this functions after adding unit tests to stakerapp -func (app *StakerApp) checkTransactionsStatus() error { +// TODO: Refactor this functions after adding unit tests to stakerapp, because of lint complexity +// nolint:maintidx,gocyclo +func (app *App) checkTransactionsStatus() error { app.logger.Debug("Start checking transaction status to fix db state") stakingParams, err := app.babylonClient.Params() @@ -696,6 +696,7 @@ func (app *StakerApp) checkTransactionsStatus() error { for _, localInfo := range transactionsOnBabylon { // we only can have one local states here + //nolint:gocritic if localInfo.stakingTxState == proto.TransactionState_SENT_TO_BABYLON { stakingTxHash := localInfo.stakingTxHash // we crashed after successful send to babylon, restart checking for unbonding signatures @@ -826,7 +827,7 @@ func (app *StakerApp) checkTransactionsStatus() error { } // waitForStakingTxConfirmation should be run in separate goroutine -func (app *StakerApp) waitForStakingTxConfirmation( +func (app *App) waitForStakingTxConfirmation( txHash chainhash.Hash, depthOnBtcChain uint32, ev *notifier.ConfirmationEvent) { @@ -876,7 +877,7 @@ func (app *StakerApp) waitForStakingTxConfirmation( } } -func (app *StakerApp) getSlashingFee(feeFromBabylon btcutil.Amount) btcutil.Amount { +func (app *App) getSlashingFee(feeFromBabylon btcutil.Amount) btcutil.Amount { if feeFromBabylon < minSlashingFee { app.logger.WithFields(logrus.Fields{ "babylonSlashingFee": feeFromBabylon, @@ -889,7 +890,7 @@ func (app *StakerApp) getSlashingFee(feeFromBabylon btcutil.Amount) btcutil.Amou } // helper to retrieve transaction when we are sure it must be in the store -func (app *StakerApp) mustGetTransactionAndStakerAddress(txHash *chainhash.Hash) (*stakerdb.StoredTransaction, btcutil.Address) { +func (app *App) mustGetTransactionAndStakerAddress(txHash *chainhash.Hash) (*stakerdb.StoredTransaction, btcutil.Address) { ts, err := app.txTracker.GetTransaction(txHash) if err != nil { @@ -905,7 +906,7 @@ func (app *StakerApp) mustGetTransactionAndStakerAddress(txHash *chainhash.Hash) return ts, stakerAddress } -func (app *StakerApp) mustBuildInclusionProof( +func (app *App) mustBuildInclusionProof( inclusionBlock *wire.MsgBlock, txIndex uint32, ) []byte { @@ -920,7 +921,7 @@ func (app *StakerApp) mustBuildInclusionProof( return proof } -func (app *StakerApp) retrieveExternalDelegationData(stakerAddress btcutil.Address) (*externalDelegationData, error) { +func (app *App) retrieveExternalDelegationData(stakerAddress btcutil.Address) (*externalDelegationData, error) { params, err := app.babylonClient.Params() if err != nil { return nil, err @@ -939,7 +940,7 @@ func (app *StakerApp) retrieveExternalDelegationData(stakerAddress btcutil.Addre }, nil } -func (app *StakerApp) sendUnbondingTxToBtcWithWitness( +func (app *App) sendUnbondingTxToBtcWithWitness( stakingTxHash *chainhash.Hash, stakerAddress btcutil.Address, storedTx *stakerdb.StoredTransaction, @@ -1036,7 +1037,7 @@ func (app *StakerApp) sendUnbondingTxToBtcWithWitness( // sendUnbondingTxToBtc sends unbonding tx to btc and registers for inclusion notification. // It retries until it successfully sends unbonding tx to btc and registers for notification.or until program finishes // TODO: Investigate whether some of the errors should be treated as fatal and abort whole process -func (app *StakerApp) sendUnbondingTxToBtc( +func (app *App) sendUnbondingTxToBtc( ctx context.Context, stakingTxHash *chainhash.Hash, stakerAddress btcutil.Address, @@ -1093,7 +1094,7 @@ func (app *StakerApp) sendUnbondingTxToBtc( } // waitForUnbondingTxConfirmation blocks until unbonding tx is confirmed on btc chain. -func (app *StakerApp) waitForUnbondingTxConfirmation( +func (app *App) waitForUnbondingTxConfirmation( waitEv *notifier.ConfirmationEvent, unbondingData *stakerdb.UnbondingStoreData, stakingTxHash *chainhash.Hash, @@ -1138,7 +1139,7 @@ func (app *StakerApp) waitForUnbondingTxConfirmation( // sendUnbondingTxToBtcTask tries to send unbonding tx to btc and register for confirmation notification. // it should be run in separate go routine. -func (app *StakerApp) sendUnbondingTxToBtcTask( +func (app *App) sendUnbondingTxToBtcTask( stakingTxHash *chainhash.Hash, stakerAddress btcutil.Address, storedTx *stakerdb.StoredTransaction, @@ -1169,7 +1170,7 @@ func (app *StakerApp) sendUnbondingTxToBtcTask( } // context which will be cancelled when app is shutting down -func (app *StakerApp) appQuitContext() (context.Context, func()) { +func (app *App) appQuitContext() (context.Context, func()) { ctx, cancel := context.WithCancel(context.Background()) app.wg.Add(1) go func() { @@ -1186,24 +1187,24 @@ func (app *StakerApp) appQuitContext() (context.Context, func()) { return ctx, cancel } -func (app *StakerApp) buildAndSendDelegation( +func (app *App) buildAndSendDelegation( req *sendDelegationRequest, stakerAddress btcutil.Address, storedTx *stakerdb.StoredTransaction, -) (*pv.RelayerTxResponse, *cl.DelegationData, error) { +) (*cl.DelegationData, error) { delegation, err := app.buildDelegation(req, stakerAddress, storedTx) if err != nil { - return nil, nil, err + return nil, err } - resp, err := app.babylonMsgSender.SendDelegation(delegation, req.requiredInclusionBlockDepth) + _, err = app.babylonMsgSender.SendDelegation(delegation, req.requiredInclusionBlockDepth) if err != nil { - return nil, nil, err + return nil, err } - return resp, delegation, nil + return delegation, nil } -func (app *StakerApp) sendDelegationToBabylonTask( +func (app *App) sendDelegationToBabylonTask( req *sendDelegationRequest, stakerAddress btcutil.Address, storedTx *stakerdb.StoredTransaction, @@ -1216,7 +1217,7 @@ func (app *StakerApp) sendDelegationToBabylonTask( var delegationData *cl.DelegationData err := retry.Do(func() error { - _, del, err := app.buildAndSendDelegation(req, stakerAddress, storedTx) + del, err := app.buildAndSendDelegation(req, stakerAddress, storedTx) if err != nil { if errors.Is(err, cl.ErrInvalidBabylonExecution) { @@ -1257,7 +1258,7 @@ func (app *StakerApp) sendDelegationToBabylonTask( } } -func (app *StakerApp) handlePreApprovalCmd( +func (app *App) handlePreApprovalCmd( cmd *stakingRequestCmd, stakingTx *wire.MsgTx, stakingOutputIdx uint32, @@ -1284,7 +1285,7 @@ func (app *StakerApp) handlePreApprovalCmd( requiredInclusionBlockDepth: cmd.requiredDepthOnBtcChain, } - _, delegationData, err := app.buildAndSendDelegation( + delegationData, err := app.buildAndSendDelegation( req, cmd.stakerAddress, fakeStoredTx, @@ -1315,7 +1316,7 @@ func (app *StakerApp) handlePreApprovalCmd( return &stakingTxHash, nil } -func (app *StakerApp) handlePostApprovalCmd( +func (app *App) handlePostApprovalCmd( cmd *stakingRequestCmd, stakingTx *wire.MsgTx, stakingOutputIdx uint32, @@ -1371,7 +1372,7 @@ func (app *StakerApp) handlePostApprovalCmd( return &stakingTxHash, nil } -func (app *StakerApp) handleStakingCmd(cmd *stakingRequestCmd) (*chainhash.Hash, error) { +func (app *App) handleStakingCmd(cmd *stakingRequestCmd) (*chainhash.Hash, error) { // Create unsigned transaction by wallet without signing. Signing will happen // in next steps stakingTx, err := app.wc.CreateTransaction( @@ -1386,12 +1387,11 @@ func (app *StakerApp) handleStakingCmd(cmd *stakingRequestCmd) (*chainhash.Hash, if cmd.usePreApprovalFlow { return app.handlePreApprovalCmd(cmd, stakingTx, 0) - } else { - return app.handlePostApprovalCmd(cmd, stakingTx, 0) } + return app.handlePostApprovalCmd(cmd, stakingTx, 0) } -func (app *StakerApp) handleStakingCommands() { +func (app *App) handleStakingCommands() { defer app.wg.Done() for { @@ -1464,7 +1464,7 @@ func (app *StakerApp) handleStakingCommands() { } // main event loop for the staker app -func (app *StakerApp) handleStakingEvents() { +func (app *App) handleStakingEvents() { defer app.wg.Done() for { @@ -1642,15 +1642,15 @@ func (app *StakerApp) handleStakingEvents() { } } -func (app *StakerApp) Wallet() walletcontroller.WalletController { +func (app *App) Wallet() walletcontroller.WalletController { return app.wc } -func (app *StakerApp) BabylonController() cl.BabylonClient { +func (app *App) BabylonController() cl.BabylonClient { return app.babylonClient } -func (app *StakerApp) WatchStaking( +func (app *App) WatchStaking( stakingTx *wire.MsgTx, stakingTime uint16, stakingValue btcutil.Amount, @@ -1737,7 +1737,7 @@ func (app *StakerApp) WatchStaking( } } -func (app *StakerApp) filterUtxoFnGen() walletcontroller.UseUtxoFn { +func (app *App) filterUtxoFnGen() walletcontroller.UseUtxoFn { return func(utxo walletcontroller.Utxo) bool { outpoint := utxo.OutPoint @@ -1751,7 +1751,7 @@ func (app *StakerApp) filterUtxoFnGen() walletcontroller.UseUtxoFn { } } -func (app *StakerApp) StakeFunds( +func (app *App) StakeFunds( stakerAddress btcutil.Address, stakingAmount btcutil.Amount, fpPks []*btcec.PublicKey, @@ -1891,7 +1891,7 @@ func (app *StakerApp) StakeFunds( } } -func (app *StakerApp) StoredTransactions(limit, offset uint64) (*stakerdb.StoredTransactionQueryResult, error) { +func (app *App) StoredTransactions(limit, offset uint64) (*stakerdb.StoredTransactionQueryResult, error) { query := stakerdb.StoredTransactionQuery{ IndexOffset: offset, NumMaxTransactions: limit, @@ -1905,7 +1905,7 @@ func (app *StakerApp) StoredTransactions(limit, offset uint64) (*stakerdb.Stored return &resp, nil } -func (app *StakerApp) WithdrawableTransactions(limit, offset uint64) (*stakerdb.StoredTransactionQueryResult, error) { +func (app *App) WithdrawableTransactions(limit, offset uint64) (*stakerdb.StoredTransactionQueryResult, error) { query := stakerdb.StoredTransactionQuery{ IndexOffset: offset, NumMaxTransactions: limit, @@ -1919,15 +1919,15 @@ func (app *StakerApp) WithdrawableTransactions(limit, offset uint64) (*stakerdb. return &resp, nil } -func (app *StakerApp) GetStoredTransaction(txHash *chainhash.Hash) (*stakerdb.StoredTransaction, error) { +func (app *App) GetStoredTransaction(txHash *chainhash.Hash) (*stakerdb.StoredTransaction, error) { return app.txTracker.GetTransaction(txHash) } -func (app *StakerApp) ListUnspentOutputs() ([]walletcontroller.Utxo, error) { +func (app *App) ListUnspentOutputs() ([]walletcontroller.Utxo, error) { return app.wc.ListOutputs(false) } -func (app *StakerApp) waitForSpendConfirmation(stakingTxHash chainhash.Hash, ev *notifier.ConfirmationEvent) { +func (app *App) waitForSpendConfirmation(stakingTxHash chainhash.Hash, ev *notifier.ConfirmationEvent) { // check we are not shutting down select { case <-app.quit: @@ -1968,7 +1968,7 @@ func (app *StakerApp) waitForSpendConfirmation(stakingTxHash chainhash.Hash, ev } } -func (app *StakerApp) signTaprootScriptSpendUsingWallet( +func (app *App) signTaprootScriptSpendUsingWallet( txToSign *wire.MsgTx, fundingOutput *wire.TxOut, signerAddress btcutil.Address, @@ -2005,7 +2005,7 @@ func (app *StakerApp) signTaprootScriptSpendUsingWallet( // unbonding of his stake. // We find in which type of output stake is locked by checking state of staking transaction, and build // proper spend transaction based on that state. -func (app *StakerApp) SpendStake(stakingTxHash *chainhash.Hash) (*chainhash.Hash, *btcutil.Amount, error) { +func (app *App) SpendStake(stakingTxHash *chainhash.Hash) (*chainhash.Hash, *btcutil.Amount, error) { // check we are not shutting down select { case <-app.quit: @@ -2136,7 +2136,7 @@ func (app *StakerApp) SpendStake(stakingTxHash *chainhash.Hash) (*chainhash.Hash return spendTxHash, &spendTxValue, nil } -func (app *StakerApp) ListActiveFinalityProviders(limit uint64, offset uint64) (*cl.FinalityProvidersClientResponse, error) { +func (app *App) ListActiveFinalityProviders(limit uint64, offset uint64) (*cl.FinalityProvidersClientResponse, error) { return app.babylonClient.QueryFinalityProviders(limit, offset) } @@ -2150,7 +2150,7 @@ func (app *StakerApp) ListActiveFinalityProviders(limit uint64, offset uint64) ( // 5. After gathering all signatures, unbonding transaction is sent to bitcoin // This function returns control to the caller after step 3. Later is up to the caller // to check what is state of unbonding transaction -func (app *StakerApp) UnbondStaking( +func (app *App) UnbondStaking( stakingTxHash chainhash.Hash) (*chainhash.Hash, error) { // check we are not shutting down select { diff --git a/staker/stakercontroller.go b/staker/stakercontroller.go index 0e0d0c1..f0f2c4d 100644 --- a/staker/stakercontroller.go +++ b/staker/stakercontroller.go @@ -7,8 +7,8 @@ import ( "github.com/btcsuite/btcd/chaincfg" ) -// Stateless controller for different client operations -type StakerController struct { +// Controller for different client operations +type Controller struct { BabylonClient cl.BabylonClient Wc walletcontroller.WalletController network *chaincfg.Params @@ -17,7 +17,7 @@ type StakerController struct { func NewStakerControllerFromClients( wc walletcontroller.WalletController, babylonClient cl.BabylonClient, -) (*StakerController, error) { +) (*Controller, error) { networkName := wc.NetworkName() params, err := ut.GetBtcNetworkParams(networkName) @@ -26,7 +26,7 @@ func NewStakerControllerFromClients( return nil, err } - return &StakerController{ + return &Controller{ Wc: wc, network: params, BabylonClient: babylonClient, diff --git a/staker/types.go b/staker/types.go index e47888e..62fb152 100644 --- a/staker/types.go +++ b/staker/types.go @@ -239,6 +239,7 @@ func createSpendStakeTxFromStoredTx( // This is to cover cases: // - staker is unable to sent delegation to babylon // - staking transaction on babylon fail to get covenant signatures + //nolint:gocritic if storedtx.StakingTxConfirmedOnBtc() && !storedtx.UnbondingTxConfirmedOnBtc() { stakingInfo, err := staking.BuildStakingInfo( stakerBtcPk, @@ -325,9 +326,8 @@ func createSpendStakeTxFromStoredTx( fundingOutputSpendInfo: unbondingTimeLockPathInfo, calculatedFee: *calculatedFee, }, nil - } else { - return nil, fmt.Errorf("cannot build spend stake transactions.Staking transaction is in invalid state: %s", storedtx.State) } + return nil, fmt.Errorf("cannot build spend stake transactions.Staking transaction is in invalid state: %s", storedtx.State) } type UnbondingSlashingDesc struct { @@ -662,9 +662,8 @@ func haveDuplicates(btcPKs []*btcec.PublicKey) bool { if _, found := seen[pkStr]; found { return true - } else { - seen[pkStr] = struct{}{} } + seen[pkStr] = struct{}{} } return false diff --git a/stakercfg/config.go b/stakercfg/config.go index c8a4ef4..3eaad64 100644 --- a/stakercfg/config.go +++ b/stakercfg/config.go @@ -2,6 +2,7 @@ package stakercfg import ( "encoding/hex" + "errors" "fmt" "io" "net" @@ -265,7 +266,8 @@ func LoadConfig() (*Config, *logrus.Logger, *zap.Logger, error) { // If it's a parsing related error, then we'll return // immediately, otherwise we can proceed as possibly the config // file doesn't exist which is OK. - if _, ok := err.(*flags.IniError); ok { + var iniErr *flags.IniError + if errors.As(err, &iniErr) { return nil, nil, nil, err } @@ -285,7 +287,8 @@ func LoadConfig() (*Config, *logrus.Logger, *zap.Logger, error) { cleanCfg, err := ValidateConfig(cfg) if err != nil { // Log help message in case of usage error. - if _, ok := err.(*usageError); ok { + var usageErr *usageError + if errors.As(err, &usageErr) { cfgLogger.Warnf("Incorrect usage: %v", usageMessage) } @@ -358,11 +361,12 @@ func ValidateConfig(cfg Config) (*Config, error) { // Show a nicer error message if it's because a symlink // is linked to a directory that does not exist // (probably because it's not mounted). - if e, ok := err.(*os.PathError); ok && os.IsExist(err) { - link, lerr := os.Readlink(e.Path) + var pathErr *os.PathError + if errors.As(err, &pathErr) && os.IsExist(err) { + link, lerr := os.Readlink(pathErr.Path) if lerr == nil { str := "is symlink %s -> %s mounted?" - err = fmt.Errorf(str, e.Path, link) + err = fmt.Errorf(str, pathErr.Path, link) } } diff --git a/stakerdb/trackedtranactionstore.go b/stakerdb/trackedtranactionstore.go index 7848c0b..86db762 100644 --- a/stakerdb/trackedtranactionstore.go +++ b/stakerdb/trackedtranactionstore.go @@ -1235,13 +1235,14 @@ func (c *TrackedTransactionStore) QueryStoredTransactions(q StoredTransactionQue return false, nil } - if txFromDB.StakingTxConfirmedOnBtc() && !txFromDB.UnbondingTxConfirmedOnBtc() { + switch { + case txFromDB.StakingTxConfirmedOnBtc() && !txFromDB.UnbondingTxConfirmedOnBtc(): scriptTimeLock = txFromDB.StakingTime confirmationHeight = txFromDB.StakingTxConfirmationInfo.Height - } else if txFromDB.StakingTxConfirmedOnBtc() && txFromDB.UnbondingTxConfirmedOnBtc() { + case txFromDB.StakingTxConfirmedOnBtc() && txFromDB.UnbondingTxConfirmedOnBtc(): scriptTimeLock = txFromDB.UnbondingTxData.UnbondingTime confirmationHeight = txFromDB.UnbondingTxData.UnbondingTxConfirmationInfo.Height - } else { + default: return false, nil } @@ -1254,13 +1255,12 @@ func (c *TrackedTransactionStore) QueryStoredTransactions(q StoredTransactionQue if timeLockExpired { resp.Transactions = append(resp.Transactions, *txFromDB) return true, nil - } else { - return false, nil } - } else { - resp.Transactions = append(resp.Transactions, *txFromDB) - return true, nil + + return false, nil } + resp.Transactions = append(resp.Transactions, *txFromDB) + return true, nil } if err := paginator.query(accumulateTransactions); err != nil { diff --git a/stakerservice/service.go b/stakerservice/service.go index 6f56168..a9b2358 100644 --- a/stakerservice/service.go +++ b/stakerservice/service.go @@ -42,14 +42,14 @@ type StakerService struct { started int32 config *scfg.Config - staker *str.StakerApp + staker *str.App logger *logrus.Logger db kvdb.Backend } func NewStakerService( c *scfg.Config, - s *str.StakerApp, + s *str.App, l *logrus.Logger, db kvdb.Backend, ) *StakerService { @@ -191,12 +191,12 @@ type PageParams struct { func getPageParams(offsetPtr *int, limitPtr *int) (*PageParams, error) { var limit uint64 - - if limitPtr == nil { + switch { + case limitPtr == nil: limit = defaultLimit - } else if *limitPtr < 0 { + case *limitPtr < 0: return nil, fmt.Errorf("limit cannot be negative") - } else { + default: limit = uint64(*limitPtr) } @@ -205,13 +205,13 @@ func getPageParams(offsetPtr *int, limitPtr *int) (*PageParams, error) { } var offset uint64 - - if offsetPtr == nil { + switch { + case offsetPtr == nil: offset = defaultOffset - } else if *offsetPtr < 0 { - return nil, fmt.Errorf("offset cannot be negative") - } else { + case *offsetPtr >= 0: offset = uint64(*offsetPtr) + default: + return nil, fmt.Errorf("offset cannot be negative") } return &PageParams{