From 748748ed5fa924f7508dc86fb0a821504e2b75c6 Mon Sep 17 00:00:00 2001 From: Lazar <12626340+Lazar955@users.noreply.github.com> Date: Thu, 14 Nov 2024 07:26:55 +0100 Subject: [PATCH] chore(*): fix golangci lint config (#93) * fix lint config * changelog * batch 1 of fixes * batch 2 of fixes * batch 3 of fixes * batch 4 of fixes --- .golangci.yml | 80 ++++++++ CHANGELOG.md | 3 + babylonclient/babyloncontroller.go | 24 +-- babylonclient/interface.go | 26 +-- babylonclient/msgsender.go | 23 ++- babylonclient/utils.go | 1 - cmd/stakercli/admin/admin.go | 8 +- cmd/stakercli/daemon/daemoncommands.go | 18 +- cmd/stakercli/main.go | 8 +- cmd/stakercli/transaction/transactions.go | 62 +++--- .../transaction/transactions_test.go | 10 +- cmd/stakerd/main.go | 8 +- itest/e2e_test.go | 35 ++-- metrics/prometheus.go | 1 + staker/babylontypes.go | 29 ++- staker/commands.go | 4 +- staker/events.go | 27 ++- staker/feeestimator.go | 1 - staker/nodebackend.go | 2 +- staker/stakerapp.go | 179 +++++++++--------- staker/stakercontroller.go | 13 +- staker/types.go | 32 ++-- stakercfg/babylon.go | 2 +- stakercfg/bitcoind.go | 4 +- stakercfg/config.go | 50 ++--- stakercfg/dbcfg.go | 6 +- stakercfg/utils.go | 24 ++- stakerdb/errors.go | 4 +- stakerdb/paginator.go | 1 - stakerdb/trackedtranactionstore.go | 104 +++++----- stakerdb/trackedtransactionstore_test.go | 33 ++-- stakerservice/client/rpcclient.go | 27 ++- stakerservice/service.go | 40 ++-- types/walletbackend.go | 1 - walletcontroller/client.go | 62 +++--- walletcontroller/transaction.go | 2 - 36 files changed, 499 insertions(+), 455 deletions(-) create mode 100644 .golangci.yml diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..717f7ad --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,80 @@ +run: + timeout: 5m + +linters: + disable-all: true + enable: + - asasalint + - asciicheck + - bidichk + - bodyclose + - containedctx + - contextcheck + - decorder + - dogsled + - durationcheck + - errcheck + - errchkjson + - errname + - errorlint + - exhaustive + - forbidigo + - forcetypeassert + - goconst + - gocritic + - gocyclo + - goheader + - gomodguard + - goprintffuncname + - gosimple + - govet + - grouper + - importas + - ineffassign + - loggercheck + - maintidx + - makezero + - misspell + - nakedret + - nilerr + # - nlreturn # Style wise I personally like this one, todo(lazar): unlax at somepoint, good practice + - noctx + - nonamedreturns + - nosprintfhostport + - paralleltest + - reassign + - revive + - rowserrcheck + - sqlclosecheck + - staticcheck + - stylecheck + - tenv + - testableexamples + - tparallel + - typecheck + - unconvert + - unparam + - usestdlibvars + - unused + - wastedassign + - whitespace +# - wrapcheck # we really should be using this, lax for now todo(lazar): unlax at somepoint, good practice + +issues: + max-same-issues: 0 + # Default: https://golangci-lint.run/usage/false-positives/#default-exclusions + exclude-dirs: + - e2etest + - itest + exclude-rules: + # Exclude some linters from running on tests files. + - path: _test\.go + linters: + - gocyclo + - errcheck + - dupl + - gosec + - gocritic + - path-except: _test\.go + linters: + - forbidigo \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 0644188..b88004c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ## Unreleased +* [#93](https://github.com/babylonlabs-io/btc-staker/pull/93) Fix linting config + + ## v0.10.0 * [#87](https://github.com/babylonlabs-io/btc-staker/pull/87) Bump babylon v15 diff --git a/babylonclient/babyloncontroller.go b/babylonclient/babyloncontroller.go index c995597..50c4378 100644 --- a/babylonclient/babyloncontroller.go +++ b/babylonclient/babyloncontroller.go @@ -16,7 +16,6 @@ import ( "github.com/avast/retry-go/v4" bbnclient "github.com/babylonlabs-io/babylon/client/client" bbntypes "github.com/babylonlabs-io/babylon/types" - bcctypes "github.com/babylonlabs-io/babylon/x/btccheckpoint/types" btclctypes "github.com/babylonlabs-io/babylon/x/btclightclient/types" btcstypes "github.com/babylonlabs-io/babylon/x/btcstaking/types" "github.com/babylonlabs-io/btc-staker/stakercfg" @@ -135,7 +134,7 @@ func (bc *BabylonController) Stop() error { func (bc *BabylonController) Params() (*StakingParams, error) { // TODO: it would probably be good to have separate methods for those - var bccParams *bcctypes.Params + var bccParams *btcctypes.Params if err := retry.Do(func() error { response, err := bc.bbnClient.BTCCheckpointParams() if err != nil { @@ -181,8 +180,8 @@ func (bc *BabylonController) Params() (*StakingParams, error) { } return &StakingParams{ - ConfirmationTimeBlocks: uint32(bccParams.BtcConfirmationDepth), - FinalizationTimeoutBlocks: uint32(bccParams.CheckpointFinalizationTimeout), + ConfirmationTimeBlocks: bccParams.BtcConfirmationDepth, + FinalizationTimeoutBlocks: bccParams.CheckpointFinalizationTimeout, SlashingPkScript: stakingTrackerParams.SlashingPkScript, CovenantPks: stakingTrackerParams.CovenantPks, MinSlashingTxFeeSat: stakingTrackerParams.MinSlashingFee, @@ -375,13 +374,13 @@ func delegationDataToMsg(dg *DelegationData) (*btcstypes.MsgCreateBTCDelegation, slashUnbondingTxSig := bbntypes.NewBIP340SignatureFromBTCSig(dg.Ud.SlashUnbondingTransactionSig) - var stakingTransactionInclusionProof *btcstypes.InclusionProof = nil + var stakingTransactionInclusionProof *btcstypes.InclusionProof if dg.StakingTransactionInclusionInfo != nil { inclusionBlockHash := bbntypes.NewBTCHeaderHashBytesFromChainhash( dg.StakingTransactionInclusionInfo.StakingTransactionInclusionBlockHash, ) - txKey := &bcctypes.TransactionKey{ + txKey := &btcctypes.TransactionKey{ Index: dg.StakingTransactionInclusionInfo.StakingTransactionIdx, Hash: &inclusionBlockHash, } @@ -670,7 +669,6 @@ func (bc *BabylonController) QueryHeaderDepth(headerHash *chainhash.Hash) (uint3 "error": err, }).Error("Failed to query babylon for the depth of the header") })); err != nil { - // translate errors to locally handable ones if strings.Contains(err.Error(), btclctypes.ErrHeaderDoesNotExist.Error()) { return 0, fmt.Errorf("%s: %w", err.Error(), ErrHeaderNotKnownToBabylon) @@ -681,10 +679,9 @@ func (bc *BabylonController) QueryHeaderDepth(headerHash *chainhash.Hash) (uint3 } return response.Depth, nil - } -// Insert BTC block header using rpc client +// InsertBtcBlockHeaders Insert BTC block header using rpc client func (bc *BabylonController) InsertBtcBlockHeaders(headers []*wire.BlockHeader) (*pv.RelayerTxResponse, error) { msg := &btclctypes.MsgInsertHeaders{ Signer: bc.getTxSigner(), @@ -748,7 +745,7 @@ func (bc *BabylonController) QueryDelegationInfo(stakingTxHash *chainhash.Hash) return err } - var udi *UndelegationInfo = nil + var udi *UndelegationInfo if resp.BtcDelegation.UndelegationResponse != nil { var coventSigInfos []CovenantSignatureInfo @@ -873,7 +870,7 @@ func (bc *BabylonController) QueryPendingBTCDelegations() ([]*btcstypes.BTCDeleg res, err := queryClient.BTCDelegations(ctx, &queryRequest) if err != nil { - return nil, fmt.Errorf("failed to query BTC delegations: %v", err) + return nil, fmt.Errorf("failed to query BTC delegations: %w", err) } return res.BtcDelegations, nil @@ -900,17 +897,15 @@ func (bc *BabylonController) InsertSpvProofs(submitter string, proofs []*btcctyp func (bc *BabylonController) QueryBtcLightClientTip() (*btclctypes.BTCHeaderInfoResponse, error) { res, err := bc.bbnClient.QueryClient.BTCHeaderChainTip() if err != nil { - return nil, fmt.Errorf("failed to query BTC tip: %v", err) + return nil, fmt.Errorf("failed to query BTC tip: %w", err) } return res.Header, nil } func (bc *BabylonController) ActivateDelegation( - ctx context.Context, stakingTxHash chainhash.Hash, proof *btcctypes.BTCSpvProof) (*pv.RelayerTxResponse, error) { - msg := &btcstypes.MsgAddBTCDelegationInclusionProof{ Signer: bc.getTxSigner(), StakingTxHash: stakingTxHash.String(), @@ -923,5 +918,4 @@ func (bc *BabylonController) ActivateDelegation( } return res, nil - } diff --git a/babylonclient/interface.go b/babylonclient/interface.go index eeee91d..a6ee8a9 100644 --- a/babylonclient/interface.go +++ b/babylonclient/interface.go @@ -34,25 +34,25 @@ type StakingParams struct { // The rate at which the staked funds will be slashed, expressed as a decimal. SlashingRate sdkmath.LegacyDec - // Convenant quorum threshold + // Covenant quorum threshold CovenantQuruomThreshold uint32 - // Minimum unbonding time required by bayblon + // Minimum unbonding time required by babylon MinUnbondingTime uint16 // Fee required by unbonding transaction UnbondingFee btcutil.Amount - // Minimum staking time required by bayblon + // Minimum staking time required by babylon MinStakingTime uint16 - // Maximum staking time required by bayblon + // Maximum staking time required by babylon MaxStakingTime uint16 - // Minimum staking value required by bayblon + // Minimum staking value required by babylon MinStakingValue btcutil.Amount - // Maximum staking value required by bayblon + // Maximum staking value required by babylon MaxStakingValue btcutil.Amount } @@ -124,7 +124,7 @@ func (m *MockBabylonClient) Delegate(dg *DelegationData) (*pv.RelayerTxResponse, return &pv.RelayerTxResponse{Code: 0}, nil } -func (m *MockBabylonClient) QueryFinalityProviders(limit uint64, offset uint64) (*FinalityProvidersClientResponse, error) { +func (m *MockBabylonClient) QueryFinalityProviders(_ uint64, _ uint64) (*FinalityProvidersClientResponse, error) { return &FinalityProvidersClientResponse{ FinalityProviders: []FinalityProviderInfo{*m.ActiveFinalityProvider}, Total: 1, @@ -136,26 +136,26 @@ func (m *MockBabylonClient) QueryFinalityProvider(btcPubKey *btcec.PublicKey) (* return &FinalityProviderClientResponse{ FinalityProvider: *m.ActiveFinalityProvider, }, nil - } else { - return nil, ErrFinalityProviderDoesNotExist } + + return nil, ErrFinalityProviderDoesNotExist } -func (m *MockBabylonClient) QueryHeaderDepth(headerHash *chainhash.Hash) (uint32, error) { +func (m *MockBabylonClient) QueryHeaderDepth(_ *chainhash.Hash) (uint32, error) { // return always confirmed depth 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/babylonclient/msgsender.go b/babylonclient/msgsender.go index 028de65..2660aeb 100644 --- a/babylonclient/msgsender.go +++ b/babylonclient/msgsender.go @@ -66,22 +66,22 @@ func NewBabylonMsgSender( } } -func (b *BabylonMsgSender) Start() { - b.startOnce.Do(func() { - b.wg.Add(1) - go b.handleSentToBabylon() +func (m *BabylonMsgSender) Start() { + m.startOnce.Do(func() { + m.wg.Add(1) + go m.handleSentToBabylon() }) } -func (b *BabylonMsgSender) Stop() { - b.stopOnce.Do(func() { - close(b.quit) - b.wg.Wait() +func (m *BabylonMsgSender) Stop() { + m.stopOnce.Do(func() { + close(m.quit) + m.wg.Wait() }) } // isBabylonBtcLcReady checks if Babylon BTC light client is ready to receive delegation -func (b *BabylonMsgSender) isBabylonBtcLcReady( +func (m *BabylonMsgSender) isBabylonBtcLcReady( requiredInclusionBlockDepth uint32, req *DelegationData, ) error { @@ -90,7 +90,7 @@ func (b *BabylonMsgSender) isBabylonBtcLcReady( return nil } - depth, err := b.cl.QueryHeaderDepth(req.StakingTransactionInclusionInfo.StakingTransactionInclusionBlockHash) + depth, err := m.cl.QueryHeaderDepth(req.StakingTransactionInclusionInfo.StakingTransactionInclusionBlockHash) if err != nil { // If header is not known to babylon, or it is on LCFork, then most probably @@ -103,7 +103,7 @@ func (b *BabylonMsgSender) isBabylonBtcLcReady( return fmt.Errorf("error while getting delegation data: %w", err) } - if uint32(depth) < requiredInclusionBlockDepth { + if depth < requiredInclusionBlockDepth { return fmt.Errorf("btc lc not ready, required depth: %d, current depth: %d: %w", requiredInclusionBlockDepth, depth, ErrBabylonBtcLightClientNotReady) } @@ -183,5 +183,4 @@ func (m *BabylonMsgSender) SendDelegation( m.sendDelegationRequestChan, m.quit, ) - } diff --git a/babylonclient/utils.go b/babylonclient/utils.go index 6a979c1..e0c993d 100644 --- a/babylonclient/utils.go +++ b/babylonclient/utils.go @@ -8,7 +8,6 @@ import ( ) func GenerateProof(block *wire.MsgBlock, txIdx uint32) ([]byte, error) { - headerBytes := babylontypes.NewBTCHeaderBytesFromBlockHeader(&block.Header) var txsBytes [][]byte diff --git a/cmd/stakercli/admin/admin.go b/cmd/stakercli/admin/admin.go index 641fa8a..4311332 100644 --- a/cmd/stakercli/admin/admin.go +++ b/cmd/stakercli/admin/admin.go @@ -86,7 +86,7 @@ const ( mnemonicEntropySize = 256 secp256k1Type = "secp256k1" - chainIdFlag = "chain-id" + chainIDFlag = "chain-id" keyringBackendFlag = "keyring-backend" keyNameFlag = "key-name" keyringDir = "keyring-dir" @@ -135,13 +135,13 @@ func createKeyRing(c *cli.Context) error { app := babylonApp.NewTmpBabylonApp() - chainId := c.String(chainIdFlag) + chainID := c.String(chainIDFlag) backend := c.String(keyringBackendFlag) keyName := c.String(keyNameFlag) keyDir := c.String(keyringDir) kb, err := keyring.New( - chainId, + chainID, backend, keyDir, nil, @@ -189,7 +189,7 @@ var createCosmosKeyringCommand = cli.Command{ Value: defaultBackend, }, cli.StringFlag{ - Name: chainIdFlag, + Name: chainIDFlag, Usage: "Chain ID for which account is created", Value: defaultChainID, }, diff --git a/cmd/stakercli/daemon/daemoncommands.go b/cmd/stakercli/daemon/daemoncommands.go index fe13558..f62a38a 100644 --- a/cmd/stakercli/daemon/daemoncommands.go +++ b/cmd/stakercli/daemon/daemoncommands.go @@ -240,7 +240,7 @@ var withdrawableTransactionsCmd = cli.Command{ func checkHealth(ctx *cli.Context) error { daemonAddress := ctx.String(stakingDaemonAddressFlag) - client, err := dc.NewStakerServiceJsonRpcClient(daemonAddress) + client, err := dc.NewStakerServiceJSONRPCClient(daemonAddress) if err != nil { return err } @@ -260,7 +260,7 @@ func checkHealth(ctx *cli.Context) error { func listOutputs(ctx *cli.Context) error { daemonAddress := ctx.String(stakingDaemonAddressFlag) - client, err := dc.NewStakerServiceJsonRpcClient(daemonAddress) + client, err := dc.NewStakerServiceJSONRPCClient(daemonAddress) if err != nil { return err } @@ -280,7 +280,7 @@ func listOutputs(ctx *cli.Context) error { func babylonFinalityProviders(ctx *cli.Context) error { daemonAddress := ctx.String(stakingDaemonAddressFlag) - client, err := dc.NewStakerServiceJsonRpcClient(daemonAddress) + client, err := dc.NewStakerServiceJSONRPCClient(daemonAddress) if err != nil { return err } @@ -312,7 +312,7 @@ func babylonFinalityProviders(ctx *cli.Context) error { func stake(ctx *cli.Context) error { daemonAddress := ctx.String(stakingDaemonAddressFlag) - client, err := dc.NewStakerServiceJsonRpcClient(daemonAddress) + client, err := dc.NewStakerServiceJSONRPCClient(daemonAddress) if err != nil { return err } @@ -337,7 +337,7 @@ func stake(ctx *cli.Context) error { func unstake(ctx *cli.Context) error { daemonAddress := ctx.String(stakingDaemonAddressFlag) - client, err := dc.NewStakerServiceJsonRpcClient(daemonAddress) + client, err := dc.NewStakerServiceJSONRPCClient(daemonAddress) if err != nil { return err } @@ -358,7 +358,7 @@ func unstake(ctx *cli.Context) error { func unbond(ctx *cli.Context) error { daemonAddress := ctx.String(stakingDaemonAddressFlag) - client, err := dc.NewStakerServiceJsonRpcClient(daemonAddress) + client, err := dc.NewStakerServiceJSONRPCClient(daemonAddress) if err != nil { return err } @@ -379,7 +379,7 @@ func unbond(ctx *cli.Context) error { func stakingDetails(ctx *cli.Context) error { daemonAddress := ctx.String(stakingDaemonAddressFlag) - client, err := dc.NewStakerServiceJsonRpcClient(daemonAddress) + client, err := dc.NewStakerServiceJSONRPCClient(daemonAddress) if err != nil { return err } @@ -400,7 +400,7 @@ func stakingDetails(ctx *cli.Context) error { func listStakingTransactions(ctx *cli.Context) error { daemonAddress := ctx.String(stakingDaemonAddressFlag) - client, err := dc.NewStakerServiceJsonRpcClient(daemonAddress) + client, err := dc.NewStakerServiceJSONRPCClient(daemonAddress) if err != nil { return err } @@ -432,7 +432,7 @@ func listStakingTransactions(ctx *cli.Context) error { func withdrawableTransactions(ctx *cli.Context) error { daemonAddress := ctx.String(stakingDaemonAddressFlag) - client, err := dc.NewStakerServiceJsonRpcClient(daemonAddress) + client, err := dc.NewStakerServiceJSONRPCClient(daemonAddress) if err != nil { return err } diff --git a/cmd/stakercli/main.go b/cmd/stakercli/main.go index 4a27eb4..fbb4358 100644 --- a/cmd/stakercli/main.go +++ b/cmd/stakercli/main.go @@ -18,8 +18,8 @@ func fatal(err error) { const ( btcNetworkFlag = "btc-network" btcWalletHostFlag = "btc-wallet-host" - btcWalletRpcUserFlag = "btc-wallet-rpc-user" - btcWalletRpcPassFlag = "btc-wallet-rpc-pass" + btcWalletRPCUserFlag = "btc-wallet-rpc-user" + btcWalletRPCPassFlag = "btc-wallet-rpc-pass" btcWalletPassphraseFlag = "btc-wallet-passphrase" btcWalletBackendFlag = "btc-wallet-backend" ) @@ -40,12 +40,12 @@ func main() { Value: "127.0.0.1:18554", }, cli.StringFlag{ - Name: btcWalletRpcUserFlag, + Name: btcWalletRPCUserFlag, Usage: "Bitcoin wallet rpc user", Value: "user", }, cli.StringFlag{ - Name: btcWalletRpcPassFlag, + Name: btcWalletRPCPassFlag, Usage: "Bitcoin wallet rpc password", Value: "pass", }, diff --git a/cmd/stakercli/transaction/transactions.go b/cmd/stakercli/transaction/transactions.go index da16aad..450e50a 100644 --- a/cmd/stakercli/transaction/transactions.go +++ b/cmd/stakercli/transaction/transactions.go @@ -99,7 +99,6 @@ func validateTxAgainstParams( tx *wire.MsgTx, globalParams *parser.ParsedGlobalParams, net *chaincfg.Params) *CheckPhase1StakingTxResponse { - var info []*ValidityInfo for i := len(globalParams.Versions) - 1; i >= 0; i-- { @@ -330,7 +329,7 @@ var checkPhase1StakingTransactionCmd = cli.Command{ Name: "check-phase1-staking-transaction", ShortName: "cpst", Usage: "Checks whether provided staking transactions is valid staking transaction (tx must be funded/have inputs)", - Description: "Checks staking transaction agains custom set of parameters. Use for custom transactions" + + Description: "Checks staking transaction against custom set of parameters. Use for custom transactions" + "that may not obey the global parameters. For most cases use `check-phase1-staking-transaction-params`", Flags: []cli.Flag{ cli.StringFlag{ @@ -527,7 +526,6 @@ func createPhase1StakingTransactionWithParams(ctx *cli.Context) error { if err != nil { return fmt.Errorf("error parsing file %s: %w", inputFilePath, err) - } currentNetwork, err := utils.GetBtcNetworkParams(ctx.String(networkNameFlag)) @@ -891,7 +889,6 @@ func createWithdrawalInfo( parsedStakingTransaction *btcstaking.ParsedV0StakingTx, paramsForHeight *parser.ParsedVersionedGlobalParams, net *chaincfg.Params) (*withdrawalInfo, error) { - if len(unbondingTxHex) > 0 { // withdrawal from unbonding output unbondingTx, _, err := bbn.NewBTCTxFromHex(unbondingTxHex) @@ -957,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/stakercli/transaction/transactions_test.go b/cmd/stakercli/transaction/transactions_test.go index bcde69c..8208724 100644 --- a/cmd/stakercli/transaction/transactions_test.go +++ b/cmd/stakercli/transaction/transactions_test.go @@ -71,6 +71,7 @@ var ( Versions: []*parser.VersionedGlobalParams{&defaultParam}, } + //nolint:errchkjson paramsMarshalled, _ = json.Marshal(globalParams) parsedGlobalParams, _ = parser.ParseGlobalParams(&globalParams) @@ -78,6 +79,7 @@ var ( ) func TestVerifyUnspendableKeyPath(t *testing.T) { + t.Parallel() bz, err := hex.DecodeString(unspendableKeyPath) require.NoError(t, err) @@ -162,7 +164,7 @@ func genSchnorPubKeyHex(t *testing.T) string { return hex.EncodeToString(schnorr.SerializePubKey(btcPub)) } -func appRunWithOutput(r *rand.Rand, t *testing.T, app *cli.App, arguments []string) (output string) { +func appRunWithOutput(r *rand.Rand, t *testing.T, app *cli.App, arguments []string) string { outPut := filepath.Join(t.TempDir(), fmt.Sprintf("%s-out.txt", datagen.GenRandomHexStr(r, 10))) outPutFile, err := os.Create(outPut) require.NoError(t, err) @@ -221,7 +223,7 @@ func appRunCreatePhase1WithdrawalTx(r *rand.Rand, t *testing.T, app *cli.App, ar return data } -func randRange(r *rand.Rand, min, max int) int { +func randRange(_ *rand.Rand, min, max int) int { return rand.Intn(max+1-min) + min } @@ -277,6 +279,7 @@ func createCustomValidStakeParams( } func TestCheckPhase1StakingTransactionCmd(t *testing.T) { + t.Parallel() app := testApp() stakerCliCheckP1StkTx := []string{ "stakercli", "transaction", "check-phase1-staking-transaction", @@ -593,7 +596,6 @@ func FuzzCreateWithdrawalStaking(f *testing.F) { require.Equal(t, ctrlBlockBytes, decoded.Inputs[0].TaprootLeafScript[0].ControlBlock) require.Equal(t, tli.RevealedLeaf.Script, decoded.Inputs[0].TaprootLeafScript[0].Script) require.Equal(t, tli.RevealedLeaf.LeafVersion, decoded.Inputs[0].TaprootLeafScript[0].LeafVersion) - }) } @@ -684,7 +686,7 @@ func FuzzCreateWithdrawalUnbonding(f *testing.F) { addrPkScript, err := txscript.PayToAddrScript(addr) require.NoError(t, err) require.Equal(t, addrPkScript, wtx.TxOut[0].PkScript) - require.Equal(t, int64(unbondingInfo.UnbondingOutput.Value)-fee, wtx.TxOut[0].Value) + require.Equal(t, unbondingInfo.UnbondingOutput.Value-fee, wtx.TxOut[0].Value) decodedBytes, err := base64.StdEncoding.DecodeString(wr.WithdrawalPsbtPacketBase64) require.NoError(t, err) diff --git a/cmd/stakerd/main.go b/cmd/stakerd/main.go index c8d93d9..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) } @@ -60,7 +62,7 @@ func main() { defer pprof.StopCPUProfile() } - dbBackend, err := scfg.GetDbBackend(cfg.DBConfig) + dbBackend, err := scfg.GetDBBackend(cfg.DBConfig) if err != nil { err = fmt.Errorf("failed to load db backend: %w", err) diff --git a/itest/e2e_test.go b/itest/e2e_test.go index 0412590..7fd123f 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -95,10 +95,10 @@ func defaultStakerConfig(t *testing.T, walletName, passphrase, bitcoindHost stri bitcoindPass := "pass" // Wallet configuration - defaultConfig.WalletRpcConfig.Host = bitcoindHost - defaultConfig.WalletRpcConfig.User = bitcoindUser - defaultConfig.WalletRpcConfig.Pass = bitcoindPass - defaultConfig.WalletRpcConfig.DisableTls = true + defaultConfig.WalletRPCConfig.Host = bitcoindHost + defaultConfig.WalletRPCConfig.User = bitcoindUser + defaultConfig.WalletRPCConfig.Pass = bitcoindPass + defaultConfig.WalletRPCConfig.DisableTLS = true defaultConfig.WalletConfig.WalletPass = passphrase defaultConfig.WalletConfig.WalletName = walletName @@ -141,13 +141,13 @@ 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 wg *sync.WaitGroup serviceAddress string - StakerClient *dc.StakerServiceJsonRpcClient + StakerClient *dc.StakerServiceJSONRPCClient CovenantPrivKeys []*btcec.PrivateKey BitcoindHandler *BitcoindTestHandler TestRpcClient *rpcclient.Client @@ -272,7 +272,7 @@ func StartManager( rpcHost := fmt.Sprintf("127.0.0.1:%s", bitcoind.GetPort("18443/tcp")) cfg, c := defaultStakerConfig(t, walletName, passphrase, rpcHost) cfg.BtcNodeBackendConfig.Bitcoind.RPCHost = rpcHost - cfg.WalletRpcConfig.Host = fmt.Sprintf("127.0.0.1:%s", bitcoind.GetPort("18443/tcp")) + cfg.WalletRPCConfig.Host = fmt.Sprintf("127.0.0.1:%s", bitcoind.GetPort("18443/tcp")) // update port with the dynamically allocated one from docker cfg.BabylonConfig.RPCAddr = fmt.Sprintf("http://localhost:%s", babylond.GetPort("26657/tcp")) @@ -298,7 +298,7 @@ func StartManager( require.NoError(t, err) cfg.DBConfig.DBPath = dbTempDir - dbbackend, err := stakercfg.GetDbBackend(cfg.DBConfig) + dbbackend, err := stakercfg.GetDBBackend(cfg.DBConfig) require.NoError(t, err) m := metrics.NewStakerMetrics() @@ -325,7 +325,7 @@ func StartManager( addressString := fmt.Sprintf("127.0.0.1:%d", testutil.AllocateUniquePort(t)) addrPort := netip.MustParseAddrPort(addressString) address := net.TCPAddrFromAddrPort(addrPort) - cfg.RpcListeners = append(cfg.RpcListeners, address) // todo(lazar): check with konrad who uses this + cfg.RPCListeners = append(cfg.RPCListeners, address) // todo(lazar): check with konrad who uses this stakerService := service.NewStakerService( cfg, @@ -346,7 +346,7 @@ func StartManager( // Wait for the server to start time.Sleep(3 * time.Second) - stakerClient, err := dc.NewStakerServiceJsonRpcClient("tcp://" + addressString) + stakerClient, err := dc.NewStakerServiceJSONRPCClient("tcp://" + addressString) require.NoError(t, err) return &TestManager{ @@ -398,7 +398,7 @@ func (tm *TestManager) RestartAppWithAction(t *testing.T, ctx context.Context, c logger.SetLevel(logrus.DebugLevel) logger.Out = os.Stdout - dbbackend, err := stakercfg.GetDbBackend(tm.Config.DBConfig) + dbbackend, err := stakercfg.GetDBBackend(tm.Config.DBConfig) require.NoError(t, err) m := metrics.NewStakerMetrics() stakerApp, err := staker.NewStakerAppFromConfig(tm.Config, logger, zapLogger, dbbackend, m) @@ -426,7 +426,7 @@ func (tm *TestManager) RestartAppWithAction(t *testing.T, ctx context.Context, c tm.wg = &wg tm.Db = dbbackend tm.Sa = stakerApp - stakerClient, err := dc.NewStakerServiceJsonRpcClient("tcp://" + tm.serviceAddress) + stakerClient, err := dc.NewStakerServiceJSONRPCClient("tcp://" + tm.serviceAddress) require.NoError(t, err) tm.StakerClient = stakerClient } @@ -1313,7 +1313,6 @@ func TestSendingStakingTransactionWithPreApproval(t *testing.T) { tm.mineNEmptyBlocks(t, params.ConfirmationTimeBlocks, true) _, err = tm.BabylonClient.ActivateDelegation( - context.Background(), *txHash, proof, ) @@ -1747,9 +1746,9 @@ func TestBitcoindWalletRpcApi(t *testing.T) { // hardcoded config scfg := stakercfg.DefaultConfig() - scfg.WalletRpcConfig.Host = fmt.Sprintf("127.0.0.1:%s", bitcoind.GetPort("18443/tcp")) - scfg.WalletRpcConfig.User = "user" - scfg.WalletRpcConfig.Pass = "pass" + scfg.WalletRPCConfig.Host = fmt.Sprintf("127.0.0.1:%s", bitcoind.GetPort("18443/tcp")) + scfg.WalletRPCConfig.User = "user" + scfg.WalletRPCConfig.Pass = "pass" scfg.ActiveNetParams.Name = "regtest" scfg.WalletConfig.WalletPass = passphrase scfg.WalletConfig.WalletName = walletName @@ -1757,7 +1756,7 @@ func TestBitcoindWalletRpcApi(t *testing.T) { scfg.ActiveNetParams = chaincfg.RegressionNetParams // Create wallet controller the same way as in staker program - wc, err := walletcontroller.NewRpcWalletController(&scfg) + wc, err := walletcontroller.NewRPCWalletController(&scfg) require.NoError(t, err) outputs, err := wc.ListOutputs(true) @@ -1825,7 +1824,7 @@ func TestBitcoindWalletBip322Signing(t *testing.T) { segwitAddress, err := c.GetNewAddress("") require.NoError(t, err) - controller, err := walletcontroller.NewRpcWalletController(cfg) + controller, err := walletcontroller.NewRPCWalletController(cfg) require.NoError(t, err) err = controller.UnlockWallet(30) 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 f2ad7ae..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, @@ -71,7 +71,7 @@ func (app *StakerApp) buildOwnedDelegation( externalData.babylonParams.SlashingPkScript, externalData.babylonParams.UnbondingFee, // TODO: Possiblity to customize finalization time - uint16(externalData.babylonParams.MinUnbondingTime)+1, + externalData.babylonParams.MinUnbondingTime+1, app.getSlashingFee(externalData.babylonParams.MinSlashingTxFeeSat), externalData.babylonParams.SlashingRate, app.network, @@ -133,11 +133,10 @@ 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) { - if storedTx.Watched { watchedData, err := app.txTracker.GetWatchedTransactionData(&req.txHash) @@ -169,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 indefinitly. At some point we may introduce +// 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() @@ -266,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") } @@ -301,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) { @@ -477,9 +475,8 @@ func (app *StakerApp) activateVerifiedDelegation( "stakingTxHash": stakingTxHash, }).Error("failed to send staking transaction to btc chain to activate verified delegation") } - // at this point we send signed staking transaciton to BTC chain, we will + // at this point we send signed staking transaction to BTC chain, we will // still wait for its activation - case <-app.quit: return } diff --git a/staker/commands.go b/staker/commands.go index 3f61ceb..5d82bfc 100644 --- a/staker/commands.go +++ b/staker/commands.go @@ -123,11 +123,11 @@ func newWatchedStakingCmd( } } -func (event *stakingRequestCmd) EventId() chainhash.Hash { +func (req *stakingRequestCmd) EventID() chainhash.Hash { // we do not have has for this event return chainhash.Hash{} } -func (event *stakingRequestCmd) EventDesc() string { +func (req *stakingRequestCmd) EventDesc() string { return "STAKING_REQUESTED_CMD" } 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/feeestimator.go b/staker/feeestimator.go index f1fb367..a44ad2c 100644 --- a/staker/feeestimator.go +++ b/staker/feeestimator.go @@ -36,7 +36,6 @@ func NewDynamicBtcFeeEstimator( cfg *scfg.BtcNodeBackendConfig, _ *chaincfg.Params, logger *logrus.Logger) (*DynamicBtcFeeEstimator, error) { - minFeeRate := chainfee.SatPerKVByte(cfg.MinFeeRate * 1000) maxFeeRate := chainfee.SatPerKVByte(cfg.MaxFeeRate * 1000) diff --git a/staker/nodebackend.go b/staker/nodebackend.go index fbdb9aa..ade74c2 100644 --- a/staker/nodebackend.go +++ b/staker/nodebackend.go @@ -26,7 +26,7 @@ type NodeBackend struct { // According to chain.BitcoindConfig docs it should also support tor if node backend // works over tor. func BuildDialer(rpcHost string) func(string) (net.Conn, error) { - return func(addr string) (net.Conn, error) { + return func(_ string) (net.Conn, error) { return net.Dial("tcp", rpcHost) } } diff --git a/staker/stakerapp.go b/staker/stakerapp.go index 0266b69..0f455a3 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" @@ -46,7 +45,7 @@ type externalDelegationData struct { babylonParams *cl.StakingParams } -type stakingDbInfo struct { +type stakingDBInfo struct { stakingTxHash *chainhash.Hash stakingTxState proto.TransactionState } @@ -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,10 +140,10 @@ 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) + walletClient, err := walletcontroller.NewRPCWalletController(config) if err != nil { return nil, err } @@ -169,7 +168,7 @@ func NewStakerAppFromConfig( ) if err != nil { - return nil, fmt.Errorf("unable to create height hint cache: %v", err) + return nil, fmt.Errorf("unable to create height hint cache: %w", err) } nodeNotifier, err := NewNodeBackend(config.BtcNodeBackendConfig, &config.ActiveNetParams, hintCache) @@ -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, @@ -247,23 +246,22 @@ func NewStakerAppFromDeps( // channel which receives confirmation that unbonding transaction was confirmed on BTC unbondingTxConfirmedOnBtcEvChan: make(chan *unbondingTxConfirmedOnBtcEvent), // channel which receives critical errors, critical errors are errors which we do not know - // how to handle, so we just log them. It is up to user to investigate, what had happend + // how to handle, so we just log them. It is up to user to investigate what had happened // and report the situation criticalErrorEvChan: make(chan *criticalErrorEvent), }, 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 app.logger.Infof("Connecting to node backend: %s", app.config.BtcNodeBackendConfig.Nodetype) - err := app.notifier.Start() - if err != nil { + if err := app.notifier.Start(); err != nil { startErr = err return } @@ -277,9 +275,7 @@ func (app *StakerApp) Start() error { return } - err = app.feeEstimator.Start() - - if err != nil { + if err = app.feeEstimator.Start(); err != nil { startErr = err return } @@ -312,13 +308,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 +336,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 +361,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 +379,7 @@ func (app *StakerApp) reportCriticialError( ) } -func (app *StakerApp) waitForStakingTransactionConfirmation( +func (app *App) waitForStakingTransactionConfirmation( stakingTxHash *chainhash.Hash, stakingTxPkScript []byte, requiredBlockDepth uint32, @@ -409,14 +405,13 @@ func (app *StakerApp) waitForStakingTransactionConfirmation( return nil } -func (app *StakerApp) handleBtcTxInfo( +func (app *App) handleBtcTxInfo( stakingTxHash *chainhash.Hash, txInfo *stakerdb.StoredTransaction, params *cl.StakingParams, currentBestBlockHeight uint32, txStatus walletcontroller.TxStatus, btcTxInfo *notifier.TxConfirmation) error { - switch txStatus { case walletcontroller.TxNotFound: // Most probable reason this happened is transaction was included in btc chain (removed from mempool) @@ -448,9 +443,9 @@ func (app *StakerApp) handleBtcTxInfo( }).Debug("Transaction found in chain") if currentBestBlockHeight < btcTxInfo.BlockHeight { - // This is wierd case, we retrieved transaction from btc wallet, even though wallet 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 error so that user can investigate. + // Log it as an error so that user can investigate. app.logger.WithFields(logrus.Fields{ "btcTxHash": stakingTxHash, "btcTxBlockHeight": btcTxInfo.BlockHeight, @@ -485,7 +480,6 @@ func (app *StakerApp) handleBtcTxInfo( ev, app.quit, ) - } else { app.logger.WithFields(logrus.Fields{ "btcTxHash": stakingTxHash, @@ -506,7 +500,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) } @@ -515,8 +509,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() @@ -525,17 +520,17 @@ func (app *StakerApp) checkTransactionsStatus() error { return err } - // Keep track of all staking transactions which need checking. chainhash.Hash objects are not relativly small + // Keep track of all staking transactions which need checking. chainhash.Hash objects are not relatively small // so it should not OOM even for larage database var transactionsSentToBtc []*chainhash.Hash var transactionConfirmedOnBtc []*chainhash.Hash - var transactionsOnBabylon []*stakingDbInfo + var transactionsOnBabylon []*stakingDBInfo var transactionsVerifiedOnBabylon []*chainhash.Hash reset := func() { transactionsSentToBtc = make([]*chainhash.Hash, 0) transactionConfirmedOnBtc = make([]*chainhash.Hash, 0) - transactionsOnBabylon = make([]*stakingDbInfo, 0) + transactionsOnBabylon = make([]*stakingDBInfo, 0) transactionsVerifiedOnBabylon = make([]*chainhash.Hash, 0) } @@ -544,7 +539,7 @@ func (app *StakerApp) checkTransactionsStatus() error { // to use to update transaction state. err = app.txTracker.ScanTrackedTransactions(func(tx *stakerdb.StoredTransaction) error { // TODO : We need to have another stare like UnstakeTransaction sent and store - // info about transaction sent (hash) to check wheter it was confirmed after staker + // info about transaction sent (hash) to check whether it was confirmed after staker // restarts stakingTxHash := tx.StakingTx.TxHash() switch tx.State { @@ -558,9 +553,9 @@ func (app *StakerApp) checkTransactionsStatus() error { // that we sent undelegation msg, but restart happened before we could update // database case proto.TransactionState_SENT_TO_BABYLON: - // TODO: If we will have automatic unstaking, we should check wheter tx is expired + // TODO: If we will have automatic unstaking, we should check whether tx is expired // and proceed with sending unstake transaction - transactionsOnBabylon = append(transactionsOnBabylon, &stakingDbInfo{ + transactionsOnBabylon = append(transactionsOnBabylon, &stakingDBInfo{ stakingTxHash: &stakingTxHash, stakingTxState: tx.State, }) @@ -569,13 +564,13 @@ func (app *StakerApp) checkTransactionsStatus() error { transactionsVerifiedOnBabylon = append(transactionsVerifiedOnBabylon, &stakingTxHash) return nil case proto.TransactionState_DELEGATION_ACTIVE: - transactionsOnBabylon = append(transactionsOnBabylon, &stakingDbInfo{ + transactionsOnBabylon = append(transactionsOnBabylon, &stakingDBInfo{ stakingTxHash: &stakingTxHash, stakingTxState: tx.State, }) return nil case proto.TransactionState_UNBONDING_CONFIRMED_ON_BTC: - transactionsOnBabylon = append(transactionsOnBabylon, &stakingDbInfo{ + transactionsOnBabylon = append(transactionsOnBabylon, &stakingDBInfo{ stakingTxHash: &stakingTxHash, stakingTxState: tx.State, }) @@ -698,9 +693,10 @@ 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 succesful send to babaylon, restart checking for unbonding signatures + // we crashed after successful send to babylon, restart checking for unbonding signatures app.wg.Add(1) go app.checkForUnbondingTxSignaturesOnBabylon(stakingTxHash) } else if localInfo.stakingTxState == proto.TransactionState_DELEGATION_ACTIVE { @@ -828,7 +824,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) { @@ -878,7 +874,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, @@ -891,7 +887,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 { @@ -907,7 +903,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 { @@ -922,7 +918,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 @@ -941,13 +937,12 @@ 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, unbondingData *stakerdb.UnbondingStoreData, ) error { - stakerPubKey, err := app.wc.AddressPublicKey(stakerAddress) if err != nil { @@ -1038,14 +1033,13 @@ 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 wheter some of the errors should be treated as fatal and abort whole process -func (app *StakerApp) sendUnbondingTxToBtc( +// TODO: Investigate whether some of the errors should be treated as fatal and abort whole process +func (app *App) sendUnbondingTxToBtc( ctx context.Context, stakingTxHash *chainhash.Hash, stakerAddress btcutil.Address, storedTx *stakerdb.StoredTransaction, unbondingData *stakerdb.UnbondingStoreData) (*notifier.ConfirmationEvent, error) { - err := retry.Do(func() error { return app.sendUnbondingTxToBtcWithWitness( stakingTxHash, @@ -1097,7 +1091,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, @@ -1142,7 +1136,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, @@ -1173,7 +1167,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() { @@ -1190,24 +1184,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, @@ -1220,7 +1214,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) { @@ -1261,7 +1255,7 @@ func (app *StakerApp) sendDelegationToBabylonTask( } } -func (app *StakerApp) handlePreApprovalCmd( +func (app *App) handlePreApprovalCmd( cmd *stakingRequestCmd, stakingTx *wire.MsgTx, stakingOutputIdx uint32, @@ -1272,7 +1266,7 @@ func (app *StakerApp) handlePreApprovalCmd( stakingOutputIdx, cmd.stakingTime, cmd.fpBtcPks, - babylonPopToDbPop(cmd.pop), + babylonPopToDBPop(cmd.pop), cmd.stakerAddress, ) @@ -1288,7 +1282,7 @@ func (app *StakerApp) handlePreApprovalCmd( requiredInclusionBlockDepth: cmd.requiredDepthOnBtcChain, } - _, delegationData, err := app.buildAndSendDelegation( + delegationData, err := app.buildAndSendDelegation( req, cmd.stakerAddress, fakeStoredTx, @@ -1303,7 +1297,7 @@ func (app *StakerApp) handlePreApprovalCmd( stakingOutputIdx, cmd.stakingTime, cmd.fpBtcPks, - babylonPopToDbPop(cmd.pop), + babylonPopToDBPop(cmd.pop), cmd.stakerAddress, delegationData.Ud.UnbondingTransaction, delegationData.Ud.UnbondingTxUnbondingTime, @@ -1319,7 +1313,7 @@ func (app *StakerApp) handlePreApprovalCmd( return &stakingTxHash, nil } -func (app *StakerApp) handlePostApprovalCmd( +func (app *App) handlePostApprovalCmd( cmd *stakingRequestCmd, stakingTx *wire.MsgTx, stakingOutputIdx uint32, @@ -1356,7 +1350,7 @@ func (app *StakerApp) handlePostApprovalCmd( &stakingTxHash, stakingOutputPkScript, cmd.requiredDepthOnBtcChain, - uint32(bestBlockHeight), + bestBlockHeight, ); err != nil { return nil, err } @@ -1366,7 +1360,7 @@ func (app *StakerApp) handlePostApprovalCmd( stakingOutputIdx, cmd.stakingTime, cmd.fpBtcPks, - babylonPopToDbPop(cmd.pop), + babylonPopToDBPop(cmd.pop), cmd.stakerAddress, ); err != nil { return nil, err @@ -1375,7 +1369,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( @@ -1390,12 +1384,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 { @@ -1411,7 +1404,7 @@ func (app *StakerApp) handleStakingCommands() { cmd.watchTxData.stakingOutputIdx, cmd.stakingTime, cmd.fpBtcPks, - babylonPopToDbPop(cmd.pop), + babylonPopToDBPop(cmd.pop), cmd.stakerAddress, cmd.watchTxData.slashingTx, cmd.watchTxData.slashingTxSig, @@ -1433,7 +1426,7 @@ func (app *StakerApp) handleStakingCommands() { &cmd.watchTxData.stakingTxHash, cmd.watchTxData.stakingTx.TxOut[cmd.watchTxData.stakingOutputIdx].PkScript, cmd.requiredDepthOnBtcChain, - uint32(bestBlockHeight), + bestBlockHeight, ); err != nil { cmd.errChan <- err continue @@ -1468,7 +1461,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 { @@ -1532,7 +1525,7 @@ func (app *StakerApp) handleStakingEvents() { if err := app.txTracker.SetTxUnbondingSignaturesReceived( &ev.stakingTxHash, - babylonCovSigsToDbSigSigs(ev.covenantUnbondingSignatures), + babylonCovSigsToDBSigSigs(ev.covenantUnbondingSignatures), ); err != nil { // TODO: handle this error somehow, it means we possilbly make invalid state transition app.logger.Fatalf("Error setting state for tx %s: %s", &ev.stakingTxHash, err) @@ -1646,15 +1639,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, @@ -1741,7 +1734,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 @@ -1755,14 +1748,13 @@ func (app *StakerApp) filterUtxoFnGen() walletcontroller.UseUtxoFn { } } -func (app *StakerApp) StakeFunds( +func (app *App) StakeFunds( stakerAddress btcutil.Address, stakingAmount btcutil.Amount, fpPks []*btcec.PublicKey, stakingTimeBlocks uint16, sendToBabylonFirst bool, ) (*chainhash.Hash, error) { - // check we are not shutting down select { case <-app.quit: @@ -1815,7 +1807,7 @@ func (app *StakerApp) StakeFunds( return nil, err } - // build proof of possesion, no point moving forward if staker do not have all + // build proof of possession, no point moving forward if staker do not have all // the necessary keys stakerPubKey, err := app.wc.AddressPublicKey(stakerAddress) @@ -1896,7 +1888,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, @@ -1910,7 +1902,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, @@ -1924,15 +1916,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: @@ -1973,14 +1965,13 @@ 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, leaf *txscript.TapLeaf, controlBlock *txscript.ControlBlock, ) (*walletcontroller.TaprootSigningResult, error) { - if err := app.wc.UnlockWallet(defaultWalletUnlockTimeout); err != nil { return nil, fmt.Errorf("failed to unlock wallet before signing: %w", err) } @@ -2011,7 +2002,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: @@ -2142,7 +2133,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) } @@ -2156,7 +2147,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 { @@ -2185,7 +2176,7 @@ func (app *StakerApp) UnbondStaking( stakerAddress, err := btcutil.DecodeAddress(tx.StakerAddress, app.network) if err != nil { - return nil, fmt.Errorf("error decoding staker address: %s. Err: %v", tx.StakerAddress, err) + return nil, fmt.Errorf("error decoding staker address: %s. Err: %w", tx.StakerAddress, err) } // TODO: Move this to event handler to avoid somebody starting multiple unbonding routines diff --git a/staker/stakercontroller.go b/staker/stakercontroller.go index 7b08cec..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 @@ -16,9 +16,8 @@ type StakerController struct { func NewStakerControllerFromClients( wc walletcontroller.WalletController, - BabylonClient cl.BabylonClient, -) (*StakerController, error) { - + babylonClient cl.BabylonClient, +) (*Controller, error) { networkName := wc.NetworkName() params, err := ut.GetBtcNetworkParams(networkName) @@ -27,9 +26,9 @@ func NewStakerControllerFromClients( return nil, err } - return &StakerController{ + return &Controller{ Wc: wc, network: params, - BabylonClient: BabylonClient, + BabylonClient: babylonClient, }, err } diff --git a/staker/types.go b/staker/types.go index d0e22b4..62fb152 100644 --- a/staker/types.go +++ b/staker/types.go @@ -7,7 +7,6 @@ import ( "sort" sdkmath "cosmossdk.io/math" - "github.com/babylonlabs-io/babylon/btcstaking" staking "github.com/babylonlabs-io/babylon/btcstaking" bbn "github.com/babylonlabs-io/babylon/types" @@ -33,23 +32,23 @@ type spendStakeTxInfo struct { calculatedFee btcutil.Amount } -// babylonPopToDbPop receives already validated pop from external sources and converts it to database representation -func babylonPopToDbPop(pop *cl.BabylonPop) *stakerdb.ProofOfPossession { +// babylonPopToDBPop receives already validated pop from external sources and converts it to database representation +func babylonPopToDBPop(pop *cl.BabylonPop) *stakerdb.ProofOfPossession { return &stakerdb.ProofOfPossession{ BtcSigType: pop.PopTypeNum(), BtcSigOverBabylonAddr: pop.BtcSig, } } -func babylonCovSigToDbCovSig(covSig cl.CovenantSignatureInfo) stakerdb.PubKeySigPair { +func babylonCovSigToDBCovSig(covSig cl.CovenantSignatureInfo) stakerdb.PubKeySigPair { return stakerdb.NewCovenantMemberSignature(covSig.Signature, covSig.PubKey) } -func babylonCovSigsToDbSigSigs(covSigs []cl.CovenantSignatureInfo) []stakerdb.PubKeySigPair { +func babylonCovSigsToDBSigSigs(covSigs []cl.CovenantSignatureInfo) []stakerdb.PubKeySigPair { sigSigs := make([]stakerdb.PubKeySigPair, len(covSigs)) for i := range covSigs { - sigSigs[i] = babylonCovSigToDbCovSig(covSigs[i]) + sigSigs[i] = babylonCovSigToDBCovSig(covSigs[i]) } return sigSigs @@ -78,7 +77,6 @@ func createWitnessSignaturesForPubKeys( covenantQuorum uint32, receivedSignaturePairs []stakerdb.PubKeySigPair, ) ([]*schnorr.Signature, error) { - if len(receivedSignaturePairs) < int(covenantQuorum) { return nil, fmt.Errorf("not enough signatures to create witness. Required: %d, received: %d", covenantQuorum, len(receivedSignaturePairs)) } @@ -131,7 +129,7 @@ func slashingTxForStakingTx( ) if err != nil { - return nil, nil, fmt.Errorf("buidling slashing transaction failed: %w", err) + return nil, nil, fmt.Errorf("building slashing transaction failed: %w", err) } stakingInfo, err := staking.BuildStakingInfo( @@ -166,8 +164,7 @@ func createDelegationData( babylonStakerAddr sdk.AccAddress, undelegationData *cl.UndelegationData, ) *cl.DelegationData { - - var incInfo *cl.StakingTransactionInclusionInfo = nil + var incInfo *cl.StakingTransactionInclusionInfo if inclusionInfo != nil { inclusionBlockHash := inclusionInfo.inclusionBlock.BlockHash() @@ -220,7 +217,7 @@ func createSpendStakeTx( fee := txrules.FeeForSerializeSize(btcutil.Amount(feeRate), txSize) - spendTx.TxOut[0].Value = spendTx.TxOut[0].Value - int64(fee) + spendTx.TxOut[0].Value -= int64(fee) if spendTx.TxOut[0].Value <= 0 { return nil, nil, fmt.Errorf("too big fee rate for spend stake tx. calculated fee: %d. funding output value: %d", fee, fundingOutput.Value) @@ -242,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, @@ -328,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 { @@ -516,7 +513,7 @@ func parseWatchStakingRequest( return nil, fmt.Errorf("failed to watch staking tx. Unbonding time must be greater than min unbonding time. Unbonding time: %d, min unbonding time: %d", unbondingTime, currentParams.MinUnbondingTime) } - // 2. Check wheter slashing tx match staking tx + // 2. Check whether slashing tx match staking tx err = staking.CheckSlashingTxMatchFundingTx( slashingTx, stakingTx, @@ -557,7 +554,7 @@ func parseWatchStakingRequest( } // 6. Validate unbonding related data - if err := btcstaking.IsSimpleTransfer(unbondingTx); err != nil { + if err := staking.IsSimpleTransfer(unbondingTx); err != nil { return nil, fmt.Errorf("failed to watch staking tx. Invalid unbonding tx: %w", err) } @@ -637,7 +634,7 @@ func parseWatchStakingRequest( req := newWatchedStakingCmd( stakerAddress, stakingTx, - uint32(stakingOutputIdx), + stakingOutputIdx, stakingTx.TxOut[stakingOutputIdx].PkScript, stakingTime, stakingValue, @@ -665,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/babylon.go b/stakercfg/babylon.go index e845097..1f8983a 100644 --- a/stakercfg/babylon.go +++ b/stakercfg/babylon.go @@ -25,7 +25,7 @@ type BBNConfig struct { func DefaultBBNConfig() BBNConfig { dc := bbncfg.DefaultBabylonConfig() - //fill up the config from dc config + // fill up the config from dc config return BBNConfig{ Key: dc.Key, ChainID: dc.ChainID, diff --git a/stakercfg/bitcoind.go b/stakercfg/bitcoind.go index 8d78177..ab16d03 100644 --- a/stakercfg/bitcoind.go +++ b/stakercfg/bitcoind.go @@ -10,7 +10,7 @@ const ( DefaultTxPollingJitter = 0.5 DefaultEstimateMode = "CONSERVATIVE" - defaultBitcoindRpcHost = "127.0.0.1:8334" + defaultBitcoindRPCHost = "127.0.0.1:8334" defaultBitcoindRPCUser = "user" defaultBitcoindRPCPass = "pass" defaultBitcoindBlockCacheSize = 20 * 1024 * 1024 // 20 MB @@ -41,7 +41,7 @@ type Bitcoind struct { func DefaultBitcoindConfig() Bitcoind { return Bitcoind{ - RPCHost: defaultBitcoindRpcHost, + RPCHost: defaultBitcoindRPCHost, RPCUser: defaultBitcoindRPCUser, RPCPass: defaultBitcoindRPCPass, RPCPolling: true, diff --git a/stakercfg/config.go b/stakercfg/config.go index 1437907..3eaad64 100644 --- a/stakercfg/config.go +++ b/stakercfg/config.go @@ -2,6 +2,7 @@ package stakercfg import ( "encoding/hex" + "errors" "fmt" "io" "net" @@ -73,25 +74,25 @@ func DefaultWalletConfig() WalletConfig { } } -type WalletRpcConfig struct { +type WalletRPCConfig struct { Host string `long:"wallethost" description:"location of the wallet rpc server"` User string `long:"walletuser" description:"user auth for the wallet rpc server"` Pass string `long:"walletpassword" description:"password auth for the wallet rpc server"` - DisableTls bool `long:"noclienttls" description:"disables tls for the wallet rpc client"` + DisableTLS bool `long:"noclienttls" description:"disables tls for the wallet rpc client"` RPCWalletCert string `long:"rpcwalletcert" description:"File containing the wallet daemon's certificate file"` RawRPCWalletCert string `long:"rawrpcwalletcert" description:"The raw bytes of the wallet daemon's PEM-encoded certificate chain which will be used to authenticate the RPC connection."` } -func DefaultWalletRpcConfig() WalletRpcConfig { - return WalletRpcConfig{ - DisableTls: true, +func DefaultWalletRPCConfig() WalletRPCConfig { + return WalletRPCConfig{ + DisableTLS: true, Host: "localhost:18556", User: "rpcuser", Pass: "rpcpass", } } -type JsonRpcServerConfig struct { +type JSONRPCServerConfig struct { RawRPCListeners []string `long:"rpclisten" description:"Add an interface/port/socket to listen for RPC connections"` } @@ -125,7 +126,7 @@ func DefaultBtcNodeBackendConfig() BtcNodeBackendConfig { type StakerConfig struct { BabylonStallingInterval time.Duration `long:"babylonstallinginterval" description:"The interval for Babylon node BTC light client to catch up with the real chain before re-sending delegation request"` UnbondingTxCheckInterval time.Duration `long:"unbondingtxcheckinterval" description:"The interval for staker whether delegation received all covenant signatures"` - CheckActiveInterval time.Duration `long:"checkactiveinterval" description:"The interval for staker to check wheter delegation is active on Babylon node"` + CheckActiveInterval time.Duration `long:"checkactiveinterval" description:"The interval for staker to check whether delegation is active on Babylon node"` MaxConcurrentTransactions uint32 `long:"maxconcurrenttransactions" description:"Maximum concurrent transactions in flight to babylon node"` ExitOnCriticalError bool `long:"exitoncriticalerror" description:"Exit stakerd on critical error"` } @@ -152,7 +153,7 @@ type Config struct { WalletConfig *WalletConfig `group:"walletconfig" namespace:"walletconfig"` - WalletRpcConfig *WalletRpcConfig `group:"walletrpcconfig" namespace:"walletrpcconfig"` + WalletRPCConfig *WalletRPCConfig `group:"walletrpcconfig" namespace:"walletrpcconfig"` ChainConfig *ChainConfig `group:"chain" namespace:"chain"` @@ -166,15 +167,15 @@ type Config struct { MetricsConfig *MetricsConfig `group:"metricsconfig" namespace:"metricsconfig"` - JsonRpcServerConfig *JsonRpcServerConfig + JSONRPCServerConfig *JSONRPCServerConfig ActiveNetParams chaincfg.Params - RpcListeners []net.Addr + RPCListeners []net.Addr } func DefaultConfig() Config { - rpcConf := DefaultWalletRpcConfig() + rpcConf := DefaultWalletRPCConfig() walletConf := DefaultWalletConfig() chainCfg := DefaultChainConfig() nodeBackendCfg := DefaultBtcNodeBackendConfig() @@ -189,7 +190,7 @@ func DefaultConfig() Config { DebugLevel: defaultLogLevel, LogDir: defaultLogDir, WalletConfig: &walletConf, - WalletRpcConfig: &rpcConf, + WalletRPCConfig: &rpcConf, ChainConfig: &chainCfg, BtcNodeBackendConfig: &nodeBackendCfg, BabylonConfig: &bbnConfig, @@ -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) } @@ -337,6 +340,8 @@ func LoadConfig() (*Config, *logrus.Logger, *zap.Logger, error) { // ValidateConfig check the given configuration to be sane. This makes sure no // illegal values or combination of values are set. All file system paths are // normalized. The cleaned up config is returned on success. +// +//nolint:gocyclo func ValidateConfig(cfg Config) (*Config, error) { // If the provided stakerd directory is not the default, we'll modify the // path to all of the files and directories that will live within it. @@ -356,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) } } @@ -491,10 +497,10 @@ func ValidateConfig(cfg Config) (*Config, error) { // At least one RPCListener is required. So listen on localhost per // default. - if len(cfg.JsonRpcServerConfig.RawRPCListeners) == 0 { + if len(cfg.JSONRPCServerConfig.RawRPCListeners) == 0 { addr := fmt.Sprintf("localhost:%d", DefaultRPCPort) - cfg.JsonRpcServerConfig.RawRPCListeners = append( - cfg.JsonRpcServerConfig.RawRPCListeners, addr, + cfg.JSONRPCServerConfig.RawRPCListeners = append( + cfg.JSONRPCServerConfig.RawRPCListeners, addr, ) } @@ -506,8 +512,8 @@ func ValidateConfig(cfg Config) (*Config, error) { // Add default port to all RPC listener addresses if needed and remove // duplicate addresses. - cfg.RpcListeners, err = lncfg.NormalizeAddresses( - cfg.JsonRpcServerConfig.RawRPCListeners, strconv.Itoa(DefaultRPCPort), + cfg.RPCListeners, err = lncfg.NormalizeAddresses( + cfg.JSONRPCServerConfig.RawRPCListeners, strconv.Itoa(DefaultRPCPort), net.ResolveTCPAddr, ) diff --git a/stakercfg/dbcfg.go b/stakercfg/dbcfg.go index 232d1f3..365a393 100644 --- a/stakercfg/dbcfg.go +++ b/stakercfg/dbcfg.go @@ -7,7 +7,7 @@ import ( ) const ( - defaultDbName = "staker.db" + defaultDBName = "staker.db" ) type DBConfig struct { @@ -43,7 +43,7 @@ type DBConfig struct { func DefaultDBConfig() DBConfig { return DBConfig{ DBPath: defaultDataDir, - DBFileName: defaultDbName, + DBFileName: defaultDBName, NoFreelistSync: true, AutoCompact: false, AutoCompactMinAge: kvdb.DefaultBoltAutoCompactMinAge, @@ -62,7 +62,7 @@ func DBConfigToBoltBackenCondfig(db *DBConfig) kvdb.BoltBackendConfig { } } -func GetDbBackend(cfg *DBConfig) (kvdb.Backend, error) { +func GetDBBackend(cfg *DBConfig) (kvdb.Backend, error) { boltConfig := DBConfigToBoltBackenCondfig(cfg) return kvdb.GetBoltBackend(&boltConfig) } diff --git a/stakercfg/utils.go b/stakercfg/utils.go index 0bc84de..30e1afb 100644 --- a/stakercfg/utils.go +++ b/stakercfg/utils.go @@ -13,19 +13,17 @@ func ReadCertFile(rawCert string, certFilePath string) ([]byte, error) { return nil, err } return rpcCert, nil + } + certFile, err := os.Open(certFilePath) + if err != nil { + return nil, err + } + defer certFile.Close() - } else { - certFile, err := os.Open(certFilePath) - if err != nil { - return nil, err - } - defer certFile.Close() - - rpcCert, err := io.ReadAll(certFile) - if err != nil { - return nil, err - } - - return rpcCert, nil + rpcCert, err := io.ReadAll(certFile) + if err != nil { + return nil, err } + + return rpcCert, nil } diff --git a/stakerdb/errors.go b/stakerdb/errors.go index ca0c0b1..c36f458 100644 --- a/stakerdb/errors.go +++ b/stakerdb/errors.go @@ -3,8 +3,8 @@ package stakerdb import "errors" var ( - // ErrCorruptedTransactionsDb For some reason, db on disk representation have changed - ErrCorruptedTransactionsDb = errors.New("transactions db is corrupted") + // ErrCorruptedTransactionsDB For some reason, db on disk representation have changed + ErrCorruptedTransactionsDB = errors.New("transactions db is corrupted") // ErrTransactionNotFound The transaction we try update is not found in db ErrTransactionNotFound = errors.New("transaction not found") diff --git a/stakerdb/paginator.go b/stakerdb/paginator.go index 297960c..79786c6 100644 --- a/stakerdb/paginator.go +++ b/stakerdb/paginator.go @@ -25,7 +25,6 @@ type paginator struct { // in pages. func newPaginator(c kvdb.RCursor, reversed bool, indexOffset, totalItems uint64) paginator { - return paginator{ cursor: c, reversed: reversed, diff --git a/stakerdb/trackedtranactionstore.go b/stakerdb/trackedtranactionstore.go index b091eff..86db762 100644 --- a/stakerdb/trackedtranactionstore.go +++ b/stakerdb/trackedtranactionstore.go @@ -226,7 +226,6 @@ type StoredTransactionQueryResult struct { // NewTrackedTransactionStore returns a new store backed by db func NewTrackedTransactionStore(db kvdb.Backend) (*TrackedTransactionStore, error) { - store := &TrackedTransactionStore{db} if err := store.initBuckets(); err != nil { return nil, err @@ -277,7 +276,6 @@ func protoBtcConfirmationInfoToBtcConfirmationInfo(ci *proto.BTCConfirmationInfo Height: ci.BlockHeight, BlockHash: *hash, }, nil - } func protoUnbondingDataToUnbondingStoreData(ud *proto.UnbondingTxData) (*UnbondingStoreData, error) { @@ -327,7 +325,7 @@ func protoTxToStoredTransaction(ttx *proto.TrackedTransaction) (*StoredTransacti return nil, err } - var utd *UnbondingStoreData = nil + var utd *UnbondingStoreData if ttx.UnbondingTxData != nil { unbondingData, err := protoUnbondingDataToUnbondingStoreData(ttx.UnbondingTxData) @@ -349,8 +347,7 @@ func protoTxToStoredTransaction(ttx *proto.TrackedTransaction) (*StoredTransacti return nil, fmt.Errorf("staking time is too large. Max value is %d", math.MaxUint16) } - var fpPubkeys []*btcec.PublicKey = make([]*btcec.PublicKey, len(ttx.FinalityProvidersBtcPks)) - + fpPubkeys := make([]*btcec.PublicKey, len(ttx.FinalityProvidersBtcPks)) for i, pk := range ttx.FinalityProvidersBtcPks { fpPubkeys[i], err = schnorr.ParsePubKey(pk) @@ -474,7 +471,7 @@ func getTxByHash( if maybeTx == nil { // if we have index, but do not have transaction, it means something weird happened // and we have corrupted db - return nil, nil, ErrCorruptedTransactionsDb + return nil, nil, ErrCorruptedTransactionsDB } return maybeTx, txKey, nil @@ -490,7 +487,7 @@ func saveTrackedTransaction( id *inputData, ) error { if tx == nil { - return fmt.Errorf("cannot save nil tracked transaciton") + return fmt.Errorf("cannot save nil tracked transactions") } nextTxKey := nextTxKey(txIdxBucket) @@ -519,7 +516,7 @@ func saveTrackedTransaction( if watchedTxData != nil { watchedTxBucket := rwTx.ReadWriteBucket(watchedTxDataBucketName) if watchedTxBucket == nil { - return ErrCorruptedTransactionsDb + return ErrCorruptedTransactionsDB } marshalled, err := pm.Marshal(watchedTxData) @@ -538,7 +535,7 @@ func saveTrackedTransaction( if id != nil { inputDataBucket := rwTx.ReadWriteBucket(inputsDataBucketName) if inputDataBucket == nil { - return ErrCorruptedTransactionsDb + return ErrCorruptedTransactionsDB } for _, input := range id.inputs { @@ -565,7 +562,7 @@ func (c *TrackedTransactionStore) addTransactionInternal( transactionsBucketIdxBucket := tx.ReadWriteBucket(transactionIndexName) if transactionsBucketIdxBucket == nil { - return ErrCorruptedTransactionsDb + return ErrCorruptedTransactionsDB } // check index first to avoid duplicates @@ -576,7 +573,7 @@ func (c *TrackedTransactionStore) addTransactionInternal( transactionsBucket := tx.ReadWriteBucket(transactionBucketName) if transactionsBucket == nil { - return ErrCorruptedTransactionsDb + return ErrCorruptedTransactionsDB } return saveTrackedTransaction(tx, transactionsBucketIdxBucket, transactionsBucket, txHashBytes, tt, wd, id) @@ -730,7 +727,7 @@ func (c *TrackedTransactionStore) AddTransactionSentToBabylon( } return c.addTransactionInternal( - txHashBytes[:], &msg, nil, inputData, + txHashBytes, &msg, nil, inputData, ) } @@ -781,7 +778,7 @@ func (c *TrackedTransactionStore) AddTransactionSentToBTC( } return c.addTransactionInternal( - txHashBytes[:], &msg, nil, nil, + txHashBytes, &msg, nil, nil, ) } @@ -813,8 +810,7 @@ func (c *TrackedTransactionStore) AddWatchedTransaction( return fmt.Errorf("cannot add transaction without finality providers public keys") } - var fpPubKeysBytes [][]byte = make([][]byte, len(fpPubKeys)) - + fpPubKeysBytes := make([][]byte, len(fpPubKeys)) for i, pk := range fpPubKeys { fpPubKeysBytes[i] = schnorr.SerializePubKey(pk) } @@ -881,12 +877,12 @@ func (c *TrackedTransactionStore) setTxState( transactionIdxBucket := tx.ReadWriteBucket(transactionIndexName) if transactionIdxBucket == nil { - return ErrCorruptedTransactionsDb + return ErrCorruptedTransactionsDB } transactionsBucket := tx.ReadWriteBucket(transactionBucketName) if transactionsBucket == nil { - return ErrCorruptedTransactionsDb + return ErrCorruptedTransactionsDB } maybeTx, txKey, err := getTxByHash(txHashBytes, transactionIdxBucket, transactionsBucket) @@ -898,7 +894,7 @@ func (c *TrackedTransactionStore) setTxState( var storedTx proto.TrackedTransaction err = pm.Unmarshal(maybeTx, &storedTx) if err != nil { - return ErrCorruptedTransactionsDb + return ErrCorruptedTransactionsDB } if err := stateTransitionFn(&storedTx); err != nil { @@ -923,7 +919,7 @@ func (c *TrackedTransactionStore) setTxState( if storedTx.State == proto.TransactionState_DELEGATION_ACTIVE { inputDataBucket := tx.ReadWriteBucket(inputsDataBucketName) if inputDataBucket == nil { - return ErrCorruptedTransactionsDb + return ErrCorruptedTransactionsDB } var stakingTx wire.MsgTx @@ -947,9 +943,7 @@ func (c *TrackedTransactionStore) setTxState( return err } } - } - return nil }) } @@ -1088,12 +1082,12 @@ func (c *TrackedTransactionStore) GetTransaction(txHash *chainhash.Hash) (*Store transactionIdxBucket := tx.ReadBucket(transactionIndexName) if transactionIdxBucket == nil { - return ErrCorruptedTransactionsDb + return ErrCorruptedTransactionsDB } transactionsBucket := tx.ReadBucket(transactionBucketName) if transactionsBucket == nil { - return ErrCorruptedTransactionsDb + return ErrCorruptedTransactionsDB } maybeTx, _, err := getTxByHash(txHashBytes, transactionIdxBucket, transactionsBucket) @@ -1105,16 +1099,16 @@ func (c *TrackedTransactionStore) GetTransaction(txHash *chainhash.Hash) (*Store var storedTxProto proto.TrackedTransaction err = pm.Unmarshal(maybeTx, &storedTxProto) if err != nil { - return ErrCorruptedTransactionsDb + return ErrCorruptedTransactionsDB } - txFromDb, err := protoTxToStoredTransaction(&storedTxProto) + txFromDB, err := protoTxToStoredTransaction(&storedTxProto) if err != nil { return err } - storedTx = txFromDb + storedTx = txFromDB return nil }, func() {}) @@ -1133,7 +1127,7 @@ func (c *TrackedTransactionStore) GetWatchedTransactionData(txHash *chainhash.Ha watchedTxDataBucket := tx.ReadBucket(watchedTxDataBucketName) if watchedTxDataBucket == nil { - return ErrCorruptedTransactionsDb + return ErrCorruptedTransactionsDB } maybeWatchedData := watchedTxDataBucket.Get(txHashBytes) @@ -1146,16 +1140,16 @@ func (c *TrackedTransactionStore) GetWatchedTransactionData(txHash *chainhash.Ha err := pm.Unmarshal(maybeWatchedData, &watchedDataProto) if err != nil { - return ErrCorruptedTransactionsDb + return ErrCorruptedTransactionsDB } - watchedDataFromDb, err := protoWatchedDataToWatchedTransactionData(&watchedDataProto) + watchedDataFromDB, err := protoWatchedDataToWatchedTransactionData(&watchedDataProto) if err != nil { return err } - watchedData = watchedDataFromDb + watchedData = watchedDataFromDB return nil }, func() {}) @@ -1193,13 +1187,13 @@ func (c *TrackedTransactionStore) QueryStoredTransactions(q StoredTransactionQue err := c.db.View(func(tx kvdb.RTx) error { transactionsBucket := tx.ReadBucket(transactionBucketName) if transactionsBucket == nil { - return ErrCorruptedTransactionsDb + return ErrCorruptedTransactionsDB } transactionIdxBucket := tx.ReadBucket(transactionIndexName) if transactionIdxBucket == nil { - return ErrCorruptedTransactionsDb + return ErrCorruptedTransactionsDB } numTransactions := getNumTx(transactionIdxBucket) @@ -1215,7 +1209,7 @@ func (c *TrackedTransactionStore) QueryStoredTransactions(q StoredTransactionQue q.NumMaxTransactions, ) - accumulateTransactions := func(key, transaction []byte) (bool, error) { + accumulateTransactions := func(_, transaction []byte) (bool, error) { protoTx := proto.TrackedTransaction{} err := pm.Unmarshal(transaction, &protoTx) @@ -1223,7 +1217,7 @@ func (c *TrackedTransactionStore) QueryStoredTransactions(q StoredTransactionQue return false, err } - txFromDb, err := protoTxToStoredTransaction(&protoTx) + txFromDB, err := protoTxToStoredTransaction(&protoTx) if err != nil { return false, err @@ -1235,19 +1229,20 @@ func (c *TrackedTransactionStore) QueryStoredTransactions(q StoredTransactionQue var confirmationHeight uint32 var scriptTimeLock uint16 - if txFromDb.Watched { + if txFromDB.Watched { // cannot withdraw watched transaction directly through staker program // at least for now. return false, nil } - if txFromDb.StakingTxConfirmedOnBtc() && !txFromDb.UnbondingTxConfirmedOnBtc() { - scriptTimeLock = txFromDb.StakingTime - confirmationHeight = txFromDb.StakingTxConfirmationInfo.Height - } else if txFromDb.StakingTxConfirmedOnBtc() && txFromDb.UnbondingTxConfirmedOnBtc() { - scriptTimeLock = txFromDb.UnbondingTxData.UnbondingTime - confirmationHeight = txFromDb.UnbondingTxData.UnbondingTxConfirmationInfo.Height - } else { + switch { + case txFromDB.StakingTxConfirmedOnBtc() && !txFromDB.UnbondingTxConfirmedOnBtc(): + scriptTimeLock = txFromDB.StakingTime + confirmationHeight = txFromDB.StakingTxConfirmationInfo.Height + case txFromDB.StakingTxConfirmedOnBtc() && txFromDB.UnbondingTxConfirmedOnBtc(): + scriptTimeLock = txFromDB.UnbondingTxData.UnbondingTime + confirmationHeight = txFromDB.UnbondingTxData.UnbondingTxConfirmationInfo.Height + default: return false, nil } @@ -1258,15 +1253,14 @@ func (c *TrackedTransactionStore) QueryStoredTransactions(q StoredTransactionQue ) if timeLockExpired { - resp.Transactions = append(resp.Transactions, *txFromDb) + 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 { @@ -1299,36 +1293,36 @@ func (c *TrackedTransactionStore) ScanTrackedTransactions(scanFunc StoredTransac transactionsBucket := tx.ReadBucket(transactionBucketName) if transactionsBucket == nil { - return ErrCorruptedTransactionsDb + return ErrCorruptedTransactionsDB } - return transactionsBucket.ForEach(func(k, v []byte) error { + return transactionsBucket.ForEach(func(_, v []byte) error { var storedTxProto proto.TrackedTransaction err := pm.Unmarshal(v, &storedTxProto) if err != nil { - return ErrCorruptedTransactionsDb + return ErrCorruptedTransactionsDB } - txFromDb, err := protoTxToStoredTransaction(&storedTxProto) + txFromDB, err := protoTxToStoredTransaction(&storedTxProto) if err != nil { return err } - return scanFunc(txFromDb) + return scanFunc(txFromDB) }) }, reset) } func (c *TrackedTransactionStore) OutpointUsed(op *wire.OutPoint) (bool, error) { - var used bool = false + used := false err := c.db.View(func(tx kvdb.RTx) error { inputsBucket := tx.ReadBucket(inputsDataBucketName) if inputsBucket == nil { - return ErrCorruptedTransactionsDb + return ErrCorruptedTransactionsDB } opBytes, err := outpointBytes(op) diff --git a/stakerdb/trackedtransactionstore_test.go b/stakerdb/trackedtransactionstore_test.go index 2d2be75..1d546f0 100644 --- a/stakerdb/trackedtransactionstore_test.go +++ b/stakerdb/trackedtransactionstore_test.go @@ -28,7 +28,7 @@ func MakeTestStore(t *testing.T) *stakerdb.TrackedTransactionStore { cfg.DBPath = tempDirName - backend, err := stakercfg.GetDbBackend(&cfg) + backend, err := stakercfg.GetDBBackend(&cfg) require.NoError(t, err) t.Cleanup(func() { @@ -100,6 +100,7 @@ func genNStoredTransactions(t *testing.T, r *rand.Rand, n int, maxStakingTime ui } func TestEmptyStore(t *testing.T) { + t.Parallel() r := rand.New(rand.NewSource(time.Now().UnixNano())) s := MakeTestStore(t) hash := datagen.GenRandomBtcdHash(r) @@ -176,6 +177,7 @@ func FuzzStoringTxs(f *testing.F) { } func TestStateTransitions(t *testing.T) { + t.Parallel() r := rand.New(rand.NewSource(time.Now().UnixNano())) s := MakeTestStore(t) tx := genStoredTransaction(t, r, 200) @@ -192,7 +194,7 @@ func TestStateTransitions(t *testing.T) { ) require.NoError(t, err) - // Inital state + // Initial state storedTx, err := s.GetTransaction(&txHash) require.NoError(t, err) require.Equal(t, proto.TransactionState_SENT_TO_BTC, storedTx.State) @@ -229,6 +231,7 @@ func TestStateTransitions(t *testing.T) { } func TestPaginator(t *testing.T) { + t.Parallel() r := rand.New(rand.NewSource(time.Now().UnixNano())) s := MakeTestStore(t) numTx := 45 @@ -276,19 +279,19 @@ func TestPaginator(t *testing.T) { require.Equal(t, 5, len(storedResult3.Transactions)) require.Equal(t, numTx, int(storedResult3.Total)) - var allTransactionsFromDb []stakerdb.StoredTransaction - allTransactionsFromDb = append(allTransactionsFromDb, storedResult1.Transactions...) - allTransactionsFromDb = append(allTransactionsFromDb, storedResult2.Transactions...) - allTransactionsFromDb = append(allTransactionsFromDb, storedResult3.Transactions...) + var allTransactionsFromDB []stakerdb.StoredTransaction + allTransactionsFromDB = append(allTransactionsFromDB, storedResult1.Transactions...) + allTransactionsFromDB = append(allTransactionsFromDB, storedResult2.Transactions...) + allTransactionsFromDB = append(allTransactionsFromDB, storedResult3.Transactions...) - require.Equal(t, len(generatedStoredTxs), len(allTransactionsFromDb)) + require.Equal(t, len(generatedStoredTxs), len(allTransactionsFromDB)) for i, storedTx := range generatedStoredTxs { - require.Equal(t, storedTx.StakingTx, allTransactionsFromDb[i].StakingTx) - require.Equal(t, storedTx.StakingOutputIndex, allTransactionsFromDb[i].StakingOutputIndex) - require.Equal(t, storedTx.StakingTime, allTransactionsFromDb[i].StakingTime) - require.True(t, pubKeysSliceEqual(storedTx.FinalityProvidersBtcPks, allTransactionsFromDb[i].FinalityProvidersBtcPks)) - require.Equal(t, storedTx.Pop, allTransactionsFromDb[i].Pop) - require.Equal(t, storedTx.StakerAddress, allTransactionsFromDb[i].StakerAddress) + require.Equal(t, storedTx.StakingTx, allTransactionsFromDB[i].StakingTx) + require.Equal(t, storedTx.StakingOutputIndex, allTransactionsFromDB[i].StakingOutputIndex) + require.Equal(t, storedTx.StakingTime, allTransactionsFromDB[i].StakingTime) + require.True(t, pubKeysSliceEqual(storedTx.FinalityProvidersBtcPks, allTransactionsFromDB[i].FinalityProvidersBtcPks)) + require.Equal(t, storedTx.Pop, allTransactionsFromDB[i].Pop) + require.Equal(t, storedTx.StakerAddress, allTransactionsFromDB[i].StakerAddress) } } @@ -299,7 +302,7 @@ func FuzzQuerySpendableTx(f *testing.F) { f.Fuzz(func(t *testing.T, seed int64) { r := rand.New(rand.NewSource(seed)) s := MakeTestStore(t) - // ganerate random transactions between 20 and 50 + // generate random transactions between 20 and 50 maxCreatedTx := int(r.Int31n(31) + 20) // random staking time between 150 and 250 blocks maxStakingTime := r.Int31n(101) + 150 @@ -322,7 +325,7 @@ func FuzzQuerySpendableTx(f *testing.F) { query := stakerdb.DefaultStoredTransactionQuery() // random confirmation block confirmationBlock := uint32(r.Int31n(1000) + 1) - halfOfMaxStaking := int32(maxStakingTime / 2) + halfOfMaxStaking := maxStakingTime / 2 currentBestBlock := confirmationBlock + uint32(r.Int31n(halfOfMaxStaking)+1) filteredQuery := query.WithdrawableTransactionsFilter(currentBestBlock) diff --git a/stakerservice/client/rpcclient.go b/stakerservice/client/rpcclient.go index 4dbbe26..48070cc 100644 --- a/stakerservice/client/rpcclient.go +++ b/stakerservice/client/rpcclient.go @@ -7,23 +7,23 @@ import ( jsonrpcclient "github.com/cometbft/cometbft/rpc/jsonrpc/client" ) -type StakerServiceJsonRpcClient struct { +type StakerServiceJSONRPCClient struct { client *jsonrpcclient.Client } // TODO Add some kind of timeout config -func NewStakerServiceJsonRpcClient(remoteAddress string) (*StakerServiceJsonRpcClient, error) { +func NewStakerServiceJSONRPCClient(remoteAddress string) (*StakerServiceJSONRPCClient, error) { client, err := jsonrpcclient.New(remoteAddress) if err != nil { return nil, err } - return &StakerServiceJsonRpcClient{ + return &StakerServiceJSONRPCClient{ client: client, }, nil } -func (c *StakerServiceJsonRpcClient) Health(ctx context.Context) (*service.ResultHealth, error) { +func (c *StakerServiceJSONRPCClient) Health(ctx context.Context) (*service.ResultHealth, error) { result := new(service.ResultHealth) _, err := c.client.Call(ctx, "health", map[string]interface{}{}, result) if err != nil { @@ -32,7 +32,7 @@ func (c *StakerServiceJsonRpcClient) Health(ctx context.Context) (*service.Resul return result, nil } -func (c *StakerServiceJsonRpcClient) ListOutputs(ctx context.Context) (*service.OutputsResponse, error) { +func (c *StakerServiceJSONRPCClient) ListOutputs(ctx context.Context) (*service.OutputsResponse, error) { result := new(service.OutputsResponse) _, err := c.client.Call(ctx, "list_outputs", map[string]interface{}{}, result) if err != nil { @@ -41,7 +41,7 @@ func (c *StakerServiceJsonRpcClient) ListOutputs(ctx context.Context) (*service. return result, nil } -func (c *StakerServiceJsonRpcClient) BabylonFinalityProviders(ctx context.Context, offset *int, limit *int) (*service.FinalityProvidersResponse, error) { +func (c *StakerServiceJSONRPCClient) BabylonFinalityProviders(ctx context.Context, offset *int, limit *int) (*service.FinalityProvidersResponse, error) { result := new(service.FinalityProvidersResponse) params := make(map[string]interface{}) @@ -61,7 +61,7 @@ func (c *StakerServiceJsonRpcClient) BabylonFinalityProviders(ctx context.Contex return result, nil } -func (c *StakerServiceJsonRpcClient) Stake( +func (c *StakerServiceJSONRPCClient) Stake( ctx context.Context, stakerAddress string, stakingAmount int64, @@ -85,7 +85,7 @@ func (c *StakerServiceJsonRpcClient) Stake( return result, nil } -func (c *StakerServiceJsonRpcClient) ListStakingTransactions(ctx context.Context, offset *int, limit *int) (*service.ListStakingTransactionsResponse, error) { +func (c *StakerServiceJSONRPCClient) ListStakingTransactions(ctx context.Context, offset *int, limit *int) (*service.ListStakingTransactionsResponse, error) { result := new(service.ListStakingTransactionsResponse) params := make(map[string]interface{}) @@ -105,7 +105,7 @@ func (c *StakerServiceJsonRpcClient) ListStakingTransactions(ctx context.Context return result, nil } -func (c *StakerServiceJsonRpcClient) WithdrawableTransactions(ctx context.Context, offset *int, limit *int) (*service.WithdrawableTransactionsResponse, error) { +func (c *StakerServiceJSONRPCClient) WithdrawableTransactions(ctx context.Context, offset *int, limit *int) (*service.WithdrawableTransactionsResponse, error) { result := new(service.WithdrawableTransactionsResponse) params := make(map[string]interface{}) @@ -125,7 +125,7 @@ func (c *StakerServiceJsonRpcClient) WithdrawableTransactions(ctx context.Contex return result, nil } -func (c *StakerServiceJsonRpcClient) StakingDetails(ctx context.Context, txHash string) (*service.StakingDetails, error) { +func (c *StakerServiceJSONRPCClient) StakingDetails(ctx context.Context, txHash string) (*service.StakingDetails, error) { result := new(service.StakingDetails) params := make(map[string]interface{}) @@ -138,7 +138,7 @@ func (c *StakerServiceJsonRpcClient) StakingDetails(ctx context.Context, txHash return result, nil } -func (c *StakerServiceJsonRpcClient) SpendStakingTransaction(ctx context.Context, txHash string) (*service.SpendTxDetails, error) { +func (c *StakerServiceJSONRPCClient) SpendStakingTransaction(ctx context.Context, txHash string) (*service.SpendTxDetails, error) { result := new(service.SpendTxDetails) params := make(map[string]interface{}) @@ -151,7 +151,7 @@ func (c *StakerServiceJsonRpcClient) SpendStakingTransaction(ctx context.Context return result, nil } -func (c *StakerServiceJsonRpcClient) WatchStaking( +func (c *StakerServiceJSONRPCClient) WatchStaking( ctx context.Context, stakingTx string, stakingTime int, @@ -169,7 +169,6 @@ func (c *StakerServiceJsonRpcClient) WatchStaking( unbondingTime int, popType int, ) (*service.ResultStake, error) { - result := new(service.ResultStake) params := make(map[string]interface{}) params["stakingTx"] = stakingTx @@ -195,7 +194,7 @@ func (c *StakerServiceJsonRpcClient) WatchStaking( return result, nil } -func (c *StakerServiceJsonRpcClient) UnbondStaking(ctx context.Context, txHash string) (*service.UnbondingResponse, error) { +func (c *StakerServiceJSONRPCClient) UnbondStaking(ctx context.Context, txHash string) (*service.UnbondingResponse, error) { result := new(service.UnbondingResponse) params := make(map[string]interface{}) diff --git a/stakerservice/service.go b/stakerservice/service.go index 45f5274..913f43e 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 { @@ -82,7 +82,6 @@ func (s *StakerService) stake(_ *rpctypes.Context, stakingTimeBlocks int64, sendToBabylonFirst bool, ) (*ResultStake, error) { - if stakingAmount <= 0 { return nil, fmt.Errorf("staking amount must be positive") } @@ -94,7 +93,7 @@ func (s *StakerService) stake(_ *rpctypes.Context, return nil, err } - var fpPubKeys []*btcec.PublicKey = make([]*btcec.PublicKey, 0) + fpPubKeys := make([]*btcec.PublicKey, 0) for _, fpPk := range fpBtcPks { fpPkBytes, err := hex.DecodeString(fpPk) @@ -128,7 +127,6 @@ func (s *StakerService) stake(_ *rpctypes.Context, func (s *StakerService) stakingDetails(_ *rpctypes.Context, stakingTxHash string) (*StakingDetails, error) { - txHash, err := chainhash.NewHashFromStr(stakingTxHash) if err != nil { return nil, err @@ -166,7 +164,6 @@ func (s *StakerService) spendStake(_ *rpctypes.Context, } func (s *StakerService) listOutputs(_ *rpctypes.Context) (*OutputsResponse, error) { - outputs, err := s.staker.ListUnspentOutputs() if err != nil { @@ -194,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) } @@ -208,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{ @@ -224,7 +221,6 @@ func getPageParams(offsetPtr *int, limitPtr *int) (*PageParams, error) { } func (s *StakerService) providers(_ *rpctypes.Context, offset, limit *int) (*FinalityProvidersResponse, error) { - pageParams, err := getPageParams(offset, limit) if err != nil { return nil, err @@ -300,7 +296,7 @@ func (s *StakerService) withdrawableTransactions(_ *rpctypes.Context, offset, li stakingDetails = append(stakingDetails, storedTxToStakingDetails(&tx)) } - var lastIdx string = "0" + lastIdx := "0" if len(stakingDetails) > 0 { // this should ease up pagination i.e in case when whe have 1000 transactions, and we limit query to 50 // due to filetring we can retrun response with 50 transactions when last one have index 400, @@ -405,7 +401,7 @@ func (s *StakerService) watchStaking( return nil, err } - var fpPubKeys []*btcec.PublicKey = make([]*btcec.PublicKey, 0) + fpPubKeys := make([]*btcec.PublicKey, 0) for _, fpPk := range fpBtcPks { fpPkBytes, err := hex.DecodeString(fpPk) @@ -592,8 +588,8 @@ func (s *StakerService) RunUntilShutdown(ctx context.Context) error { return fmt.Errorf(format, args...) } - err := s.staker.Start() - if err != nil { + //nolint:contextcheck + if err := s.staker.Start(); err != nil { return mkErr("error starting staker: %w", err) } @@ -609,8 +605,8 @@ func (s *StakerService) RunUntilShutdown(ctx context.Context) error { // TODO: investigate if we can use logrus directly to pass it to rpcserver rpcLogger := log.NewTMLogger(s.logger.Writer()) - listeners := make([]net.Listener, len(s.config.RpcListeners)) - for i, listenAddr := range s.config.RpcListeners { + listeners := make([]net.Listener, len(s.config.RPCListeners)) + for i, listenAddr := range s.config.RPCListeners { listenAddressStr := listenAddr.Network() + "://" + listenAddr.String() mux := http.NewServeMux() rpc.RegisterRPCFuncs(mux, routes, rpcLogger) diff --git a/types/walletbackend.go b/types/walletbackend.go index a05936f..ab7908e 100644 --- a/types/walletbackend.go +++ b/types/walletbackend.go @@ -18,5 +18,4 @@ func NewWalletBackend(backend string) (SupportedWalletBackend, error) { default: return BtcwalletWalletBackend, fmt.Errorf("invalid wallet type: %s", backend) } - } diff --git a/walletcontroller/client.go b/walletcontroller/client.go index ce48e1a..174c9cf 100644 --- a/walletcontroller/client.go +++ b/walletcontroller/client.go @@ -9,7 +9,6 @@ import ( "github.com/babylonlabs-io/babylon/crypto/bip322" "github.com/babylonlabs-io/btc-staker/stakercfg" - scfg "github.com/babylonlabs-io/btc-staker/stakercfg" "github.com/babylonlabs-io/btc-staker/types" "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" @@ -24,37 +23,37 @@ import ( notifier "github.com/lightningnetwork/lnd/chainntnfs" ) -type RpcWalletController struct { +type RPCWalletController struct { *rpcclient.Client walletPassphrase string network string backend types.SupportedWalletBackend } -var _ WalletController = (*RpcWalletController)(nil) +var _ WalletController = (*RPCWalletController)(nil) const ( txNotFoundErrMsgBtcd = "No information available about transaction" txNotFoundErrMsgBitcoind = "No such mempool or blockchain transaction" ) -func NewRpcWalletController(scfg *stakercfg.Config) (*RpcWalletController, error) { - return NewRpcWalletControllerFromArgs( - scfg.WalletRpcConfig.Host, - scfg.WalletRpcConfig.User, - scfg.WalletRpcConfig.Pass, +func NewRPCWalletController(scfg *stakercfg.Config) (*RPCWalletController, error) { + return NewRPCWalletControllerFromArgs( + scfg.WalletRPCConfig.Host, + scfg.WalletRPCConfig.User, + scfg.WalletRPCConfig.Pass, scfg.ActiveNetParams.Name, scfg.WalletConfig.WalletName, scfg.WalletConfig.WalletPass, scfg.BtcNodeBackendConfig.ActiveWalletBackend, &scfg.ActiveNetParams, - scfg.WalletRpcConfig.DisableTls, - scfg.WalletRpcConfig.RawRPCWalletCert, - scfg.WalletRpcConfig.RPCWalletCert, + scfg.WalletRPCConfig.DisableTLS, + scfg.WalletRPCConfig.RawRPCWalletCert, + scfg.WalletRPCConfig.RPCWalletCert, ) } -func NewRpcWalletControllerFromArgs( +func NewRPCWalletControllerFromArgs( host string, user string, pass string, @@ -63,15 +62,14 @@ func NewRpcWalletControllerFromArgs( walletPassphrase string, nodeBackend types.SupportedWalletBackend, params *chaincfg.Params, - disableTls bool, + disableTLS bool, rawWalletCert string, walletCertFilePath string, -) (*RpcWalletController, error) { - +) (*RPCWalletController, error) { connCfg := &rpcclient.ConnConfig{ Host: rpcHostURL(host, walletName), User: user, Pass: pass, - DisableTLS: disableTls, + DisableTLS: disableTLS, DisableConnectOnNew: true, DisableAutoReconnect: false, // we use post mode as it sure it works with either bitcoind or btcwallet @@ -80,7 +78,7 @@ func NewRpcWalletControllerFromArgs( } if !connCfg.DisableTLS { - cert, err := scfg.ReadCertFile(rawWalletCert, walletCertFilePath) + cert, err := stakercfg.ReadCertFile(rawWalletCert, walletCertFilePath) if err != nil { return nil, err } @@ -92,7 +90,7 @@ func NewRpcWalletControllerFromArgs( return nil, err } - return &RpcWalletController{ + return &RPCWalletController{ Client: rpcclient, walletPassphrase: walletPassphrase, network: params.Name, @@ -107,11 +105,11 @@ func rpcHostURL(host, walletName string) string { return host } -func (w *RpcWalletController) UnlockWallet(timoutSec int64) error { +func (w *RPCWalletController) UnlockWallet(timoutSec int64) error { return w.WalletPassphrase(w.walletPassphrase, timoutSec) } -func (w *RpcWalletController) AddressPublicKey(address btcutil.Address) (*btcec.PublicKey, error) { +func (w *RPCWalletController) AddressPublicKey(address btcutil.Address) (*btcec.PublicKey, error) { encoded := address.EncodeAddress() info, err := w.GetAddressInfo(encoded) @@ -133,17 +131,16 @@ func (w *RpcWalletController) AddressPublicKey(address btcutil.Address) (*btcec. return btcec.ParsePubKey(decodedHex) } -func (w *RpcWalletController) NetworkName() string { +func (w *RPCWalletController) NetworkName() string { return w.network } -func (w *RpcWalletController) CreateTransaction( +func (w *RPCWalletController) CreateTransaction( outputs []*wire.TxOut, feeRatePerKb btcutil.Amount, changeAddres btcutil.Address, useUtxoFn UseUtxoFn, ) (*wire.MsgTx, error) { - utxoResults, err := w.ListUnspent() if err != nil { @@ -186,7 +183,7 @@ func (w *RpcWalletController) CreateTransaction( return tx, err } -func (w *RpcWalletController) CreateAndSignTx( +func (w *RPCWalletController) CreateAndSignTx( outputs []*wire.TxOut, feeRatePerKb btcutil.Amount, changeAddress btcutil.Address, @@ -213,7 +210,7 @@ func (w *RpcWalletController) CreateAndSignTx( return fundedTx, nil } -func (w *RpcWalletController) SignRawTransaction(tx *wire.MsgTx) (*wire.MsgTx, bool, error) { +func (w *RPCWalletController) SignRawTransaction(tx *wire.MsgTx) (*wire.MsgTx, bool, error) { switch w.backend { case types.BitcoindWalletBackend: return w.Client.SignRawTransactionWithWallet(tx) @@ -224,11 +221,11 @@ func (w *RpcWalletController) SignRawTransaction(tx *wire.MsgTx) (*wire.MsgTx, b } } -func (w *RpcWalletController) SendRawTransaction(tx *wire.MsgTx, allowHighFees bool) (*chainhash.Hash, error) { +func (w *RPCWalletController) SendRawTransaction(tx *wire.MsgTx, allowHighFees bool) (*chainhash.Hash, error) { return w.Client.SendRawTransaction(tx, allowHighFees) } -func (w *RpcWalletController) ListOutputs(onlySpendable bool) ([]Utxo, error) { +func (w *RPCWalletController) ListOutputs(onlySpendable bool) ([]Utxo, error) { utxoResults, err := w.ListUnspent() if err != nil { @@ -261,7 +258,7 @@ func nofitierStateToWalletState(state notifier.TxConfStatus) TxStatus { } } -func (w *RpcWalletController) getTxDetails(req notifier.ConfRequest, msg string) (*notifier.TxConfirmation, TxStatus, error) { +func (w *RPCWalletController) getTxDetails(req notifier.ConfRequest, msg string) (*notifier.TxConfirmation, TxStatus, error) { res, state, err := notifier.ConfDetailsFromTxIndex(w.Client, req, msg) if err != nil { @@ -272,7 +269,7 @@ func (w *RpcWalletController) getTxDetails(req notifier.ConfRequest, msg string) } // Fetch info about transaction from mempool or blockchain, requires node to have enabled transaction index -func (w *RpcWalletController) TxDetails(txHash *chainhash.Hash, pkScript []byte) (*notifier.TxConfirmation, TxStatus, error) { +func (w *RPCWalletController) TxDetails(txHash *chainhash.Hash, pkScript []byte) (*notifier.TxConfirmation, TxStatus, error) { req, err := notifier.NewConfRequest(txHash, pkScript) if err != nil { @@ -294,7 +291,7 @@ func (w *RpcWalletController) TxDetails(txHash *chainhash.Hash, pkScript []byte) // - wallet must be unlocked // - address must be under wallet control // - address must be native segwit address -func (w *RpcWalletController) SignBip322NativeSegwit(msg []byte, address btcutil.Address) (wire.TxWitness, error) { +func (w *RPCWalletController) SignBip322NativeSegwit(msg []byte, address btcutil.Address) (wire.TxWitness, error) { toSpend, err := bip322.GetToSpendTx(msg, address) if err != nil { @@ -330,7 +327,7 @@ func (w *RpcWalletController) SignBip322NativeSegwit(msg []byte, address btcutil return signed.TxIn[0].Witness, nil } -func (w *RpcWalletController) OutputSpent( +func (w *RPCWalletController) OutputSpent( txHash *chainhash.Hash, outputIdx uint32, ) (bool, error) { @@ -345,7 +342,7 @@ func (w *RpcWalletController) OutputSpent( return res == nil, nil } -func (w *RpcWalletController) SignOneInputTaprootSpendingTransaction(request *TaprootSigningRequest) (*TaprootSigningResult, error) { +func (w *RPCWalletController) SignOneInputTaprootSpendingTransaction(request *TaprootSigningRequest) (*TaprootSigningResult, error) { if len(request.TxToSign.TxIn) != 1 { return nil, fmt.Errorf("cannot sign transaction with more than one input") } @@ -457,5 +454,4 @@ func (w *RpcWalletController) SignOneInputTaprootSpendingTransaction(request *Ta // neither witness, nor signature is filled. return nil, fmt.Errorf("no signature found in PSBT packet. Wallet can't sign given tx") - } diff --git a/walletcontroller/transaction.go b/walletcontroller/transaction.go index 248e7e1..6abefa7 100644 --- a/walletcontroller/transaction.go +++ b/walletcontroller/transaction.go @@ -79,7 +79,6 @@ func makeInputSource(utxos []Utxo) txauthor.InputSource { return func(target btcutil.Amount) (btcutil.Amount, []*wire.TxIn, []btcutil.Amount, [][]byte, error) { - for currentTotal < target && len(utxos) != 0 { nextCredit := &utxos[0] utxos = utxos[1:] @@ -98,7 +97,6 @@ func buildTxFromOutputs( outputs []*wire.TxOut, feeRatePerKb btcutil.Amount, changeScript []byte) (*wire.MsgTx, error) { - if len(utxos) == 0 { return nil, fmt.Errorf("there must be at least 1 usable UTXO to build transaction") }