Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: (BitcoinRBF-Step2): some minimum code refactoring for Bitcoin RBF adoption #3381

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from

Conversation

ws4charlie
Copy link
Contributor

@ws4charlie ws4charlie commented Jan 21, 2025

Description

  1. Move Bitcoin observer methods to separate files (db.go gas_price.go, utxos.go) and add a few unit tests.
  2. Move Bitcoin signing related methods to sign.go; create reusable methods AddTxInputs SignTx and unit tests.
  3. Creat GetEstimatedFeeRate Bitcoin RPC helper function.
  4. Creat reusable method TryIncludeOutbound as the only entry point for outbound inclusion. Refactor on Bitcoin outbound.go.
  5. Creat OutboundData struct to check and pass Bitcoin outbound tx data, similar to EVM chain.
  6. Simplify ObserveOutbound for outbound tracker processing.
  7. Create method BroadcastOutbound to handle tx broadcasting; add unit test.
  8. Unify Bitcoin tx size as int64 to be consistent with Bitcoin APIs, e.g. mempool.GetTxVirtualSize. The Bitcoin uses int64 to represent output value in wire.NewTxOut, so using int64 makes calculation value = txSize * feeRate easier.
  9. Renamings and other refactoring.

How Has This Been Tested?

  • Tested CCTX in localnet
  • Tested in development environment
  • Go unit tests
  • Go integration tests
  • Tested via GitHub Actions

Summary by CodeRabbit

Release Notes for ZetaChain Bitcoin Client Update

  • New Features

    • Added support for Bitcoin Replace-By-Fee (RBF) adoption
    • Enhanced Bitcoin transaction fee estimation and handling
    • Improved UTXO management for Bitcoin transactions
  • Improvements

    • Refactored Bitcoin client transaction signing and broadcasting logic
    • Updated fee rate calculation and estimation methods
    • Improved error handling and logging for Bitcoin-related operations
  • Technical Enhancements

    • Standardized Bitcoin address and transaction handling
    • Added more robust transaction inclusion and validation checks
    • Improved test coverage for Bitcoin client functionality

Copy link
Contributor

coderabbitai bot commented Jan 21, 2025

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

📝 Walkthrough

Walkthrough

This pull request introduces comprehensive refactoring and enhancements to the Bitcoin client functionality within the ZetaChain node, focusing on improving transaction handling, fee estimation, and observability. The changes span multiple components of the Bitcoin client, including observer, signer, and utility modules, with a particular emphasis on Replace-By-Fee (RBF) adoption and more robust transaction management.

Changes

File Change Summary
changelog.md Added entry for Bitcoin RBF code refactoring
testutil/sample/crypto.go Updated Bitcoin address handling, added script generation method
x/crosschain/types/cctx_test.go, x/crosschain/types/revert_options_test.go Modified Bitcoin address handling in tests
zetaclient/chains/bitcoin/* Extensive refactoring of Bitcoin client components
zetaclient/logs/fields.go Added new log field for outbound ID
zetaclient/orchestrator/orchestrator.go Updated method naming conventions
zetaclient/testdata/btc/ Added new transaction test data files

Suggested labels

bitcoin, refactor, testing, zetaclient

Possibly related PRs

Suggested Reviewers

  • skosito
  • lumtis
  • swift1337
  • fbac
  • kingpinXD

The pull request represents a significant step in improving the Bitcoin client's robustness, with particular attention to transaction fee management, address handling, and testing infrastructure. The changes demonstrate a methodical approach to refactoring, ensuring type safety, improving error handling, and enhancing the overall reliability of Bitcoin transaction processing within the ZetaChain ecosystem.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

github-actions bot commented Jan 21, 2025

!!!WARNING!!!
nosec detected in the following files: zetaclient/chains/bitcoin/observer/db.go, zetaclient/chains/bitcoin/observer/gas_price.go, zetaclient/chains/bitcoin/signer/outbound_data.go, zetaclient/chains/bitcoin/signer/sign.go, zetaclient/chains/bitcoin/common/fee.go

Be very careful about using #nosec in code. It can be a quick way to suppress security warnings and move forward with development, it should be employed with caution. Suppressing warnings with #nosec can hide potentially serious vulnerabilities. Only use #nosec when you're absolutely certain that the security issue is either a false positive or has been mitigated in another way.

Only suppress a single rule (or a specific set of rules) within a section of code, while continuing to scan for other problems. To do this, you can list the rule(s) to be suppressed within the #nosec annotation, e.g: /* #nosec G401 */ or //#nosec G201 G202 G203
Broad #nosec annotations should be avoided, as they can hide other vulnerabilities. The CI will block you from merging this PR until you remove #nosec annotations that do not target specific rules.

Pay extra attention to the way #nosec is being used in the files listed above.

@github-actions github-actions bot added the nosec label Jan 21, 2025
@ws4charlie ws4charlie marked this pull request as ready for review January 21, 2025 04:10
@ws4charlie ws4charlie requested a review from a team as a code owner January 21, 2025 04:10
@ws4charlie ws4charlie added zetaclient Issues related to ZetaClient refactor chain:bitcoin Bitcoin chain related labels Jan 21, 2025
@ws4charlie ws4charlie changed the title refactor: (BitcoinRBF-Step2): some minimum code refactoring for Bitcoin RBF integration refactor: (BitcoinRBF-Step2): some minimum code refactoring for Bitcoin RBF adoption Jan 21, 2025
Copy link

codecov bot commented Jan 21, 2025

Codecov Report

Attention: Patch coverage is 51.40187% with 312 lines in your changes missing coverage. Please review.

Project coverage is 63.93%. Comparing base (9fc89e0) to head (09fb0ac).

Files with missing lines Patch % Lines
zetaclient/chains/bitcoin/observer/outbound.go 4.49% 85 Missing ⚠️
zetaclient/chains/bitcoin/signer/sign.go 52.31% 68 Missing and 4 partials ⚠️
zetaclient/chains/bitcoin/observer/utxos.go 62.71% 42 Missing and 2 partials ⚠️
zetaclient/chains/bitcoin/observer/gas_price.go 0.00% 37 Missing ⚠️
zetaclient/chains/bitcoin/signer/signer.go 57.62% 23 Missing and 2 partials ⚠️
zetaclient/chains/bitcoin/client/helpers.go 0.00% 20 Missing ⚠️
zetaclient/orchestrator/orchestrator.go 0.00% 14 Missing ⚠️
zetaclient/chains/bitcoin/observer/db.go 78.57% 7 Missing and 2 partials ⚠️
zetaclient/chains/bitcoin/common/fee.go 89.47% 2 Missing ⚠️
zetaclient/chains/bitcoin/observer/observer.go 87.50% 2 Missing ⚠️
... and 1 more
Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop    #3381      +/-   ##
===========================================
+ Coverage    63.38%   63.93%   +0.54%     
===========================================
  Files          436      441       +5     
  Lines        30674    30725      +51     
===========================================
+ Hits         19444    19645     +201     
+ Misses       10394    10239     -155     
- Partials       836      841       +5     
Files with missing lines Coverage Δ
zetaclient/chains/bitcoin/signer/outbound_data.go 100.00% <100.00%> (ø)
zetaclient/orchestrator/v2_bootstrap.go 65.90% <ø> (ø)
zetaclient/testutils/testdata.go 87.02% <100.00%> (+0.36%) ⬆️
zetaclient/testutils/testdata_naming.go 80.85% <100.00%> (+0.85%) ⬆️
zetaclient/zetacore/broadcast.go 59.16% <100.00%> (+0.34%) ⬆️
zetaclient/chains/bitcoin/common/fee.go 43.63% <89.47%> (+4.61%) ⬆️
zetaclient/chains/bitcoin/observer/observer.go 82.82% <87.50%> (+45.54%) ⬆️
zetaclient/chains/evm/signer/signer.go 44.32% <0.00%> (ø)
zetaclient/chains/bitcoin/observer/db.go 78.57% <78.57%> (ø)
zetaclient/orchestrator/orchestrator.go 19.68% <0.00%> (ø)
... and 6 more

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 14

🔭 Outside diff range comments (4)
zetaclient/chains/bitcoin/observer/outbound_test.go (1)

Line range hint 265-349: Consider using satoshis instead of BTC for precise calculations.

The test cases use floating-point values for Bitcoin amounts, which can lead to precision issues. Consider using satoshis (integer values) for calculations to ensure exact precision.

Example conversion:

-selected, err := ob.SelectUTXOs(ctx, 0.01, 5, 0, math.MaxUint16, true)
+selected, err := ob.SelectUTXOs(ctx, 1000000, 5, 0, math.MaxUint16, true) // 0.01 BTC = 1,000,000 satoshis
zetaclient/chains/evm/signer/signer.go (1)

Line range hint 279-392: Consider refactoring complex conditional logic using a strategy pattern.

The SignOutboundFromCCTX function contains complex nested if-else statements that make the code hard to maintain. Consider using a strategy pattern to handle different transaction types.

Example approach:

type OutboundSigner interface {
    Sign(ctx context.Context, cctx *crosschaintypes.CrossChainTx, data *OutboundData) (*ethtypes.Transaction, error)
}

// Implement different strategies
type ComplianceSigner struct{}
type AdminCommandSigner struct{}
type V2ProtocolSigner struct{}
// etc.

// Factory to get appropriate signer
func GetOutboundSigner(cctx *crosschaintypes.CrossChainTx) OutboundSigner {
    // Return appropriate signer based on conditions
}
zetaclient/chains/bitcoin/signer/sign.go (1)

Line range hint 251-255: Concurrency Safety for IsTSSTransaction Method

The IsTSSTransaction method accesses the tssOutboundHashes map but does not use synchronization mechanisms. Since maps are not thread-safe in Go, consider adding a read lock to prevent concurrent access issues.

Apply this diff to add a read lock:

 func (ob *Observer) IsTSSTransaction(txid string) bool {
+    ob.Mu().RLock()
+    defer ob.Mu().RUnlock()
     _, found := ob.tssOutboundHashes[txid]
     return found
 }
zetaclient/chains/bitcoin/common/fee.go (1)

Add test coverage for GetRecentFeeRate function

The review comment is accurate. While CalcBlockAvgFeeRate has comprehensive test coverage, GetRecentFeeRate remains untested. Essential test cases should include:

  • Network parameter validation (mainnet rejection)
  • Block traversal and fee rate calculation across multiple blocks
  • Error handling for RPC failures
  • Default fee rate fallback behavior
  • Edge cases with zero fee rates

Consider following the testing patterns established in inbound_test.go, which demonstrates thorough error case coverage and proper test data management.

🔗 Analysis chain

Line range hint 250-290: Add test coverage for fee rate calculation.

The GetRecentFeeRate function lacks test coverage according to static analysis.

Consider adding test cases for:

  • Different network parameters
  • Various block fee rates
  • Error scenarios
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Find existing test files for fee rate calculation
fd -e go -E '*_test.go' fee | xargs rg -l 'TestGetRecentFeeRate|Test_GetRecentFeeRate'

Length of output: 88


Script:

#!/bin/bash
# Find all fee-related test files
fd -e go test fee

# Search for CalcBlockAvgFeeRate tests and implementations
rg -l "CalcBlockAvgFeeRate" --type go

# Look for mock RPC implementations that could be used in testing
rg -l "type.*RPC.*interface" --type go
rg -l "Mock.*RPC" --type go

Length of output: 917


Script:

#!/bin/bash
# Check test content for CalcBlockAvgFeeRate
rg -A 10 "CalcBlockAvgFeeRate" zetaclient/chains/bitcoin/observer/inbound_test.go zetaclient/chains/bitcoin/client/client_test.go

# Look for Bitcoin-specific mock implementations
rg -l "Mock.*Bitcoin.*RPC|Bitcoin.*Mock.*RPC" --type go

Length of output: 8590

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 250-250: zetaclient/chains/bitcoin/common/fee.go#L250
Added line #L250 was not covered by tests

🧹 Nitpick comments (36)
zetaclient/testutils/testdata.go (1)

120-126: LGTM! Consider adding a brief comment about the return value.

The implementation is correct and follows the established patterns. Consider adding a brief comment about the returned transaction object to maintain consistency with other functions in the file.

 // LoadBTCTransaction loads archived Bitcoin transaction from file
+// Returns the transaction details as GetTransactionResult
 func LoadBTCTransaction(t *testing.T, dir string, chainID int64, txHash string) *btcjson.GetTransactionResult {
zetaclient/testutils/mocks/zetacore_client_opts.go (1)

37-46: Consider adding parameter documentation and type-specific matchers.

While the implementation is correct, consider these improvements:

  1. Add documentation to describe the expected parameters and behavior
  2. Use type-specific matchers instead of mock.Anything where possible to catch type mismatches early in tests

Example improvement:

+// WithPostOutboundTracker sets up expectations for PostOutboundTracker method
+// Parameters:
+//   - param1: <type> - description
+//   - param2: <type> - description
+//   - param3: <type> - description
+//   - param4: <type> - description
 func (_m *ZetacoreClient) WithPostOutboundTracker(zetaTxHash string) *ZetacoreClient {
-    on := _m.On("PostOutboundTracker", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Maybe()
+    on := _m.On("PostOutboundTracker", 
+        mock.MatchedBy(func(p interface{}) bool { return true }), // Replace with type-specific matcher
+        mock.MatchedBy(func(p interface{}) bool { return true }), // Replace with type-specific matcher
+        mock.MatchedBy(func(p interface{}) bool { return true }), // Replace with type-specific matcher
+        mock.MatchedBy(func(p interface{}) bool { return true }), // Replace with type-specific matcher
+    ).Maybe()
zetaclient/orchestrator/orchestrator.go (3)

442-442: Error messages include contextual information.

The error messages in ScheduleCCTXEVM now consistently include outbound ID and chain information, which aids in debugging. However, consider standardizing the error message format.

Apply this pattern for error messages:

-Msgf("ScheduleCCTXEVM: GetAllOutboundTrackerByChain failed for chain %d", chainID)
+Msgf("ScheduleCCTXEVM: failed to get outbound tracker: chain=%d", chainID)

Also applies to: 464-464, 468-468, 478-478, 483-483, 511-511


541-541: Error messages in Solana handler follow similar pattern.

The error messages in ScheduleCCTXSolana maintain consistency with the EVM handler. However, the same message format standardization should be applied here.

Apply this pattern for error messages:

-Msgf("ScheduleCCTXSolana: chain observer is not a solana observer")
+Msgf("ScheduleCCTXSolana: invalid observer type: expected=solana")

Also applies to: 559-559, 563-563, 573-573, 578-578, 585-585


Line range hint 431-599: Consider extracting common scheduling logic.

Both ScheduleCCTXEVM and ScheduleCCTXSolana share similar patterns for:

  1. Parameter validation
  2. Outbound tracking
  3. Vote confirmation
  4. Keysign scheduling

This could be refactored into a common base implementation to reduce code duplication.

Consider creating a base scheduler that implements the common logic, with chain-specific implementations handling only the unique aspects of each chain.

zetaclient/chains/bitcoin/observer/inbound_test.go (1)

Line range hint 161-209: Consider adding more test cases for edge scenarios.

The current test suite could benefit from additional test cases to cover:

  • Extremely large transaction values
  • Malformed Bitcoin addresses
  • Maximum memo size scenarios

Example test case structure:

 tests := []struct {
     name    string
     event   *observer.BTCInboundEvent
     nilVote bool
 }{
+    {
+        name: "should return nil for extremely large value",
+        event: &observer.BTCInboundEvent{
+            Value:     math.MaxInt64,
+            MemoBytes: testutil.HexToBytes(t, "2d07a9cbd57dcca3e2cf966c88bc874445b6e3b668656c6c6f207361746f736869"),
+        },
+        nilVote: true,
+    },
+    {
+        name: "should return nil for malformed address",
+        event: &observer.BTCInboundEvent{
+            FromAddress: "invalid_address",
+            MemoBytes: testutil.HexToBytes(t, "2d07a9cbd57dcca3e2cf966c88bc874445b6e3b668656c6c6f207361746f736869"),
+        },
+        nilVote: true,
+    },
     // existing test cases...
 }
zetaclient/chains/bitcoin/observer/observer_test.go (2)

205-215: Consider adding edge cases to strengthen the test coverage.

While the basic functionality is tested, consider adding these test cases:

  • Maximum uint64 value
  • Setting nonce multiple times
  • Concurrent access scenarios

Here's a suggested enhancement:

 func Test_SetPendingNonce(t *testing.T) {
+    t.Run("basic functionality", func(t *testing.T) {
         // create observer
         ob := newTestSuite(t, chains.BitcoinMainnet, "")
 
         // ensure pending nonce is 0
         require.Zero(t, ob.GetPendingNonce())
 
         // set and get pending nonce
         nonce := uint64(100)
         ob.SetPendingNonce(nonce)
         require.Equal(t, nonce, ob.GetPendingNonce())
+    })
+
+    t.Run("edge cases", func(t *testing.T) {
+        ob := newTestSuite(t, chains.BitcoinMainnet, "")
+        
+        // Test max uint64
+        maxNonce := uint64(^uint64(0))
+        ob.SetPendingNonce(maxNonce)
+        require.Equal(t, maxNonce, ob.GetPendingNonce())
+        
+        // Test multiple updates
+        ob.SetPendingNonce(1)
+        ob.SetPendingNonce(2)
+        require.Equal(t, uint64(2), ob.GetPendingNonce())
+    })
 }

288-295: Add validation for database path.

The current implementation doesn't validate the provided dbPath. Consider adding checks for:

  • Path existence when non-empty
  • Path permissions
  • Invalid characters in path

Here's a suggested enhancement:

 if dbPath == "" {
     database, err = db.NewFromSqliteInMemory(true)
 } else {
+    // Validate database path
+    if _, err := os.Stat(dbPath); err != nil {
+        if os.IsNotExist(err) {
+            if err := os.MkdirAll(dbPath, 0755); err != nil {
+                return nil, fmt.Errorf("failed to create database directory: %w", err)
+            }
+        } else {
+            return nil, fmt.Errorf("invalid database path: %w", err)
+        }
+    }
     database, err = db.NewFromSqlite(dbPath, "test.db", true)
 }
zetaclient/chains/bitcoin/observer/outbound_test.go (3)

Line range hint 13-13: Consider using a more robust test data path resolution.

The hardcoded relative path to the testdata directory could break if the project structure changes. Consider using go-testfixtures or a similar package to handle test data paths more robustly.

-var TestDataDir = "../../../"
+var TestDataDir = filepath.Join("testdata", "bitcoin", "outbound")

Line range hint 141-241: Refactor to table-driven tests for better maintainability.

The TSS vout validation test cases contain repetitive setup code. Consider refactoring to table-driven tests to reduce duplication and make it easier to add new test cases.

func TestCheckTSSVout(t *testing.T) {
    chain := chains.BitcoinMainnet
    chainID := chain.ChainId
    nonce := uint64(148)
    ob := MockBTCObserverMainnet(t, nil)
    
    tests := []struct {
        name        string
        modifyVout  func(*btcjson.GetRawTransactionResult)
        wantErr     bool
        errContains string
    }{
        {
            name:        "valid TSS vout should pass",
            modifyVout:  func(r *btcjson.GetRawTransactionResult) {},
            wantErr:     false,
        },
        {
            name: "should fail if vout 0 is not to the TSS address",
            modifyVout: func(r *btcjson.GetRawTransactionResult) {
                r.Vout[0].ScriptPubKey.Hex = "0014ba8be635673034d4d0ddc9447409b594385ec4aa"
            },
            wantErr:     true,
            errContains: "not match TSS address",
        },
        // Add other test cases here
    }
    
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            rawResult, cctx := testutils.LoadBTCTxRawResultNCctx(t, TestDataDir, chainID, nonce)
            tt.modifyVout(rawResult)
            params := cctx.GetCurrentOutboundParam()
            
            err := ob.checkTSSVout(params, rawResult.Vout)
            if tt.wantErr {
                require.ErrorContains(t, err, tt.errContains)
            } else {
                require.NoError(t, err)
            }
        })
    }
}

Line range hint 351-471: Extract common setup code to reduce duplication.

The UTXO consolidation test cases contain repetitive setup code. Consider extracting the common setup into a helper function to improve maintainability.

func setupUTXOTest(t *testing.T, nonce uint64) *Observer {
    ob := createObserverWithUTXOs(t)
    dummyTxID := "6e6f71d281146c1fc5c755b35908ee449f26786c84e2ae18f98b268de40b7ec4"
    mineTxNSetNonceMark(t, ob, nonce, dummyTxID, -1)
    return ob
}

Then use it in the test cases:

t.Run("should not consolidate", func(t *testing.T) {
    ob := setupUTXOTest(t, 0)
    // Test logic here
})
zetaclient/chains/evm/signer/signer.go (2)

Line range hint 279-279: Address TODO comment regarding function simplification.

The TODO comment indicates technical debt that should be addressed. Would you like me to create an issue to track this improvement?


Line range hint 141-241: Consider breaking down TryProcessOutbound into smaller, focused functions.

The function is handling multiple responsibilities including context management, transaction setup, signing, and broadcasting. This makes it harder to test and maintain.

Consider extracting the following responsibilities into separate functions:

  • Transaction setup and validation
  • Error handling and recovery
  • Broadcasting logic
zetaclient/chains/bitcoin/signer/signer.go (2)

168-168: Typographical error in comment

There's a minor typo in the comment. "broacasting" should be corrected to "broadcasting" for clarity.

Apply this diff to fix the typo:

-    // try broacasting tx with increasing backoff (1s, 2s, 4s, 8s, 16s) in case of RPC error
+    // try broadcasting tx with increasing backoff (1s, 2s, 4s, 8s, 16s) in case of RPC error

168-178: Consider using a dedicated backoff library for improved retry logic

While the current exponential backoff implementation using time.Sleep functions correctly, utilizing a dedicated backoff library like go-retryablehttp can offer more features such as jitter, maximum elapsed time, and better control over retry logic.

zetaclient/chains/bitcoin/observer/utxos.go (1)

32-36: Avoid using recover to handle panics; use proper error handling instead

Relying on recover to catch panics can obscure the root causes of errors and make debugging more difficult. It's better to prevent panics by ensuring errors are properly checked and handled throughout the code.

zetaclient/chains/bitcoin/signer/sign.go (2)

227-229: Error Wrapping Enhancements for Clarity

The error message in fmt.Errorf("SignBatch failed: %v", err) could be enhanced using errors.Wrap to preserve the stack trace and provide more context.

Apply this diff to use errors.Wrap:

-	return fmt.Errorf("SignBatch failed: %v", err)
+	return errors.Wrap(err, "SignBatch failed")

Ensure that the errors package is consistently used for error wrapping throughout the codebase.


136-138: Simplify Return Statement

The return statement in AddTxInputs can be simplified by directly returning the amounts slice after the loop.

Apply this diff to simplify the code:

-    }
-
-    return amounts, nil
+    }
+    return amounts, nil
 }
zetaclient/chains/evm/rpc/rpc_live_test.go (1)

65-73: Consider enhancing gas price validation.

While the basic validation ensures non-zero gas price, consider adding upper bound checks to catch unreasonable values that might indicate network issues.

 func LiveTest_SuggestGasPrice(t *testing.T) {
     client, err := ethclient.Dial(URLBaseMainnet)
     require.NoError(t, err)

     ctx := context.Background()
     gasPrice, err := client.SuggestGasPrice(ctx)
     require.NoError(t, err)
     require.True(t, gasPrice.Cmp(big.NewInt(0)) > 0)
+    // Add reasonable upper bound check (e.g., 1000 gwei)
+    maxGasPrice := new(big.Int).Mul(big.NewInt(1000), big.NewInt(1e9))
+    require.True(t, gasPrice.Cmp(maxGasPrice) < 0, "Gas price exceeds reasonable maximum")
 }
zetaclient/chains/bitcoin/observer/gas_price.go (1)

56-70: Consider using constants for network types.

The switch statement could be more maintainable using constants for network types. Also, consider adding a default case to handle future network types.

 func (ob *Observer) specialHandleFeeRate(ctx context.Context) (int64, error) {
+    const (
+        errUnsupportedNetwork = "unsupported bitcoin network type %d"
+    )
     switch ob.Chain().NetworkType {
     case chains.NetworkType_privnet:
         return client.FeeRateRegnet, nil
     case chains.NetworkType_testnet:
         feeRateEstimated, err := common.GetRecentFeeRate(ctx, ob.rpc, ob.netParams)
         if err != nil {
             return 0, errors.Wrapf(err, "error GetRecentFeeRate")
         }
         return feeRateEstimated, nil
     default:
-        return 0, fmt.Errorf(" unsupported bitcoin network type %d", ob.Chain().NetworkType)
+        return 0, fmt.Errorf(errUnsupportedNetwork, ob.Chain().NetworkType)
     }
 }
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 57-68: zetaclient/chains/bitcoin/observer/gas_price.go#L57-L68
Added lines #L57 - L68 were not covered by tests

zetaclient/chains/bitcoin/observer/db.go (1)

57-69: Consider using transactions for map updates.

The function updates two maps independently. Consider using a transaction-like pattern to ensure atomic updates or reverting both if one fails.

 func (ob *Observer) LoadBroadcastedTxMap() error {
     var broadcastedTransactions []clienttypes.OutboundHashSQLType
     if err := ob.DB().Client().Find(&broadcastedTransactions).Error; err != nil {
         ob.logger.Chain.Error().Err(err).Msgf("error iterating over db for chain %d", ob.Chain().ChainId)
         return err
     }
+    tempOutboundHashes := make(map[string]bool)
+    tempBroadcastedTx := make(map[string]string)
     for _, entry := range broadcastedTransactions {
-        ob.tssOutboundHashes[entry.Hash] = true
-        ob.broadcastedTx[entry.Key] = entry.Hash
+        tempOutboundHashes[entry.Hash] = true
+        tempBroadcastedTx[entry.Key] = entry.Hash
     }
+    ob.Mu().Lock()
+    ob.tssOutboundHashes = tempOutboundHashes
+    ob.broadcastedTx = tempBroadcastedTx
+    ob.Mu().Unlock()
     return nil
 }
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 61-63: zetaclient/chains/bitcoin/observer/db.go#L61-L63
Added lines #L61 - L63 were not covered by tests

zetaclient/chains/bitcoin/client/mockgen.go (1)

48-48: Add method documentation.

Consider adding a comment describing the purpose, parameters, and return values of the GetEstimatedFeeRate method to maintain consistency with other interface methods.

+// GetEstimatedFeeRate returns the estimated fee rate in satoshis/vbyte for a transaction
+// to be confirmed within confTarget blocks. If regnet is true, returns a hardcoded fee rate.
 GetEstimatedFeeRate(ctx context.Context, confTarget int64, regnet bool) (int64, error)
zetaclient/zetacore/broadcast_test.go (1)

34-34: Consider adding boundary test cases.

While the error handling test cases are comprehensive, consider adding boundary test cases for the numeric parameters:

  • Maximum uint64 value for nonce
  • Negative values for chain ID
  • Zero values for both parameters
zetaclient/chains/bitcoin/observer/db_test.go (2)

47-48: Replace magic number with a named constant.

The block number 199 appears to be arbitrary. Consider defining it as a named constant to improve test readability and maintainability.

+const testLastBlockScanned = 199
-ob.WriteLastBlockScannedToDB(199)
+ob.WriteLastBlockScannedToDB(testLastBlockScanned)

76-77: Add test case for partial RPC failure.

The RPC error test only covers complete failure. Consider adding a test case where the RPC call succeeds but returns an unexpected block number.

zetaclient/chains/bitcoin/signer/sign_test.go (2)

93-257: Consider adding test cases for edge cases in fee calculation.

While the test coverage is good, consider adding test cases for:

  • Maximum possible fee scenarios
  • Minimum fee threshold scenarios
  • Fee calculation with dust amounts

259-326: Add test cases for different signature types.

The current test only verifies the presence of witness data. Consider adding test cases for:

  • Different signature types (P2PKH, P2SH, P2WPKH, P2WSH)
  • Invalid signature scenarios
  • Signature verification
zetaclient/chains/bitcoin/observer/event_test.go (1)

309-309: Consider adding test cases for empty observer chain ID.

The empty string parameter in newTestSuite calls suggests a potential edge case. Consider adding test cases for invalid chain ID scenarios.

Also applies to: 357-357, 397-397

zetaclient/chains/bitcoin/signer/signer_test.go (2)

97-170: Enhance RBF test coverage.

While the test cases cover basic RBF outbound scenarios, consider adding explicit assertions for:

  • RBF-specific attributes (sequence numbers)
  • Fee rate comparisons between original and replacement transactions
  • Multiple replacement iterations

Example test case structure:

{
    name:     "should successfully replace transaction with higher fee rate",
    chain:    chains.BitcoinMainnet,
    nonce:    uint64(148),
    feeRate:  2.0, // multiplier for replacement
    attempts: 3,   // number of replacement iterations
}

337-354: Parameterize context creation helper.

The function uses hardcoded values which limits its reusability. Consider accepting parameters for:

  • Chain selection
  • Chain parameters
-func makeCtx(t *testing.T) context.Context {
+func makeCtx(t *testing.T, chain chains.Chain, params int64) context.Context {
     app := zctx.New(config.New(false), nil, zerolog.Nop())

-    chain := chains.BitcoinMainnet
-    btcParams := mocks.MockChainParams(chain.ChainId, 2)
+    btcParams := mocks.MockChainParams(chain.ChainId, params)
changelog.md (1)

10-10: Consider expanding the changelog description.

The current description "some code refactoring in zetaclient for Bitcoin RBF adoption" could be more specific about the key refactoring changes, such as the relocation of Bitcoin observer methods and the creation of reusable methods.

Consider this more detailed description:

-* [3381](https://github.com/zeta-chain/node/pull/3381) - some code refactoring in zetaclient for Bitcoin RBF adoption
+* [3381](https://github.com/zeta-chain/node/pull/3381) - refactor Bitcoin observer methods into separate files (db.go, gas_price.go, utxos.go), add reusable methods for Bitcoin signing (AddTxInputs, SignTx), and introduce OutboundData struct for Bitcoin RBF adoption
zetaclient/chains/bitcoin/observer/observer.go (3)

107-109: Consolidate redundant comments for tssOutboundHashes

The variable tssOutboundHashes has two comments that convey similar information. Merging them into a single, concise comment will enhance code readability and maintainability.

Apply this diff to consolidate the comments:

-	// tssOutboundHashes indexes included tx with tx hash
-	// tssOutboundHashes keeps track of outbound hashes sent from TSS address
+	// tssOutboundHashes keeps track of outbound transaction hashes sent from the TSS address

198-203: Evaluate the use of atomic operations for pendingNonce

The SetPendingNonce method uses mutex locks to synchronize access to pendingNonce. As pendingNonce is of type uint64, utilizing atomic operations (e.g., atomic.LoadUint64, atomic.StoreUint64) could improve performance by reducing locking overhead while maintaining thread safety. Consider adopting atomic operations if they align with the synchronization requirements of your application.


268-269: Add unit tests for isNodeEnabled method

The isNodeEnabled method lacks test coverage, as indicated by static analysis tools. Implementing unit tests for this method will enhance code reliability and ensure that node enablement checks function as expected.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 268-269: zetaclient/chains/bitcoin/observer/observer.go#L268-L269
Added lines #L268 - L269 were not covered by tests

zetaclient/chains/bitcoin/observer/outbound.go (2)

53-53: Use formal language in log messages

The log message contains informal language ("oops"), which is not suitable for production environments. Rewriting the message with formal language enhances professionalism and clarity in the logs.

Apply this diff to update the log message:

-			ob.logger.Outbound.Warn().Msgf("oops, got multiple (%d) outbound hashes", len(tracker.HashList))
+			ob.logger.Outbound.Warn().Msgf("Detected multiple (%d) outbound hashes", len(tracker.HashList))
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 53-53: zetaclient/chains/bitcoin/observer/outbound.go#L53
Added line #L53 was not covered by tests


88-97: Add unit tests for TryIncludeOutbound method

The TryIncludeOutbound method plays a critical role in the outbound transaction flow but is not covered by unit tests. Implementing tests will verify its behavior under various conditions, such as successful inclusion, failures, and edge cases, thereby enhancing code reliability.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 88-95: zetaclient/chains/bitcoin/observer/outbound.go#L88-L95
Added lines #L88 - L95 were not covered by tests


[warning] 97-97: zetaclient/chains/bitcoin/observer/outbound.go#L97
Added line #L97 was not covered by tests

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 078dbef and 2481654.

📒 Files selected for processing (39)
  • changelog.md (1 hunks)
  • testutil/sample/crypto.go (2 hunks)
  • x/crosschain/types/cctx_test.go (1 hunks)
  • x/crosschain/types/revert_options_test.go (1 hunks)
  • zetaclient/chains/bitcoin/client/client_test.go (2 hunks)
  • zetaclient/chains/bitcoin/client/helpers.go (3 hunks)
  • zetaclient/chains/bitcoin/client/mockgen.go (1 hunks)
  • zetaclient/chains/bitcoin/common/fee.go (7 hunks)
  • zetaclient/chains/bitcoin/common/fee_test.go (11 hunks)
  • zetaclient/chains/bitcoin/observer/db.go (1 hunks)
  • zetaclient/chains/bitcoin/observer/db_test.go (1 hunks)
  • zetaclient/chains/bitcoin/observer/event_test.go (5 hunks)
  • zetaclient/chains/bitcoin/observer/gas_price.go (1 hunks)
  • zetaclient/chains/bitcoin/observer/inbound_test.go (2 hunks)
  • zetaclient/chains/bitcoin/observer/observer.go (5 hunks)
  • zetaclient/chains/bitcoin/observer/observer_test.go (5 hunks)
  • zetaclient/chains/bitcoin/observer/outbound.go (6 hunks)
  • zetaclient/chains/bitcoin/observer/outbound_test.go (7 hunks)
  • zetaclient/chains/bitcoin/observer/utxos.go (1 hunks)
  • zetaclient/chains/bitcoin/signer/outbound_data.go (1 hunks)
  • zetaclient/chains/bitcoin/signer/outbound_data_test.go (1 hunks)
  • zetaclient/chains/bitcoin/signer/sign.go (1 hunks)
  • zetaclient/chains/bitcoin/signer/sign_test.go (1 hunks)
  • zetaclient/chains/bitcoin/signer/signer.go (4 hunks)
  • zetaclient/chains/bitcoin/signer/signer_test.go (10 hunks)
  • zetaclient/chains/evm/observer/observer_test.go (0 hunks)
  • zetaclient/chains/evm/rpc/rpc_live_test.go (4 hunks)
  • zetaclient/chains/evm/signer/signer.go (1 hunks)
  • zetaclient/logs/fields.go (1 hunks)
  • zetaclient/orchestrator/orchestrator.go (10 hunks)
  • zetaclient/orchestrator/v2_bootstrap.go (0 hunks)
  • zetaclient/testdata/btc/chain_8332_msgtx_030cd813443f7b70cc6d8a544d320c6d8465e4528fc0f3410b599dc0b26753a0.json (1 hunks)
  • zetaclient/testdata/btc/chain_8332_tx_030cd813443f7b70cc6d8a544d320c6d8465e4528fc0f3410b599dc0b26753a0.json (1 hunks)
  • zetaclient/testutils/mocks/bitcoin_client.go (1 hunks)
  • zetaclient/testutils/mocks/zetacore_client_opts.go (1 hunks)
  • zetaclient/testutils/testdata.go (1 hunks)
  • zetaclient/testutils/testdata_naming.go (1 hunks)
  • zetaclient/zetacore/broadcast.go (2 hunks)
  • zetaclient/zetacore/broadcast_test.go (1 hunks)
💤 Files with no reviewable changes (2)
  • zetaclient/orchestrator/v2_bootstrap.go
  • zetaclient/chains/evm/observer/observer_test.go
✅ Files skipped from review due to trivial changes (2)
  • zetaclient/testdata/btc/chain_8332_tx_030cd813443f7b70cc6d8a544d320c6d8465e4528fc0f3410b599dc0b26753a0.json
  • zetaclient/testdata/btc/chain_8332_msgtx_030cd813443f7b70cc6d8a544d320c6d8465e4528fc0f3410b599dc0b26753a0.json
🧰 Additional context used
📓 Path-based instructions (34)
zetaclient/logs/fields.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/testutils/testdata.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/client/client_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/testutils/mocks/bitcoin_client.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

x/crosschain/types/revert_options_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

x/crosschain/types/cctx_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/evm/signer/signer.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/client/mockgen.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/testutils/testdata_naming.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/zetacore/broadcast_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

testutil/sample/crypto.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/testutils/mocks/zetacore_client_opts.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/evm/rpc/rpc_live_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/observer/db_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/signer/outbound_data_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/observer/gas_price.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/observer/inbound_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/client/helpers.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/observer/event_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/signer/outbound_data.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/observer/outbound_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/signer/signer.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/zetacore/broadcast.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/observer/observer_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/observer/utxos.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/orchestrator/orchestrator.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/signer/sign.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/observer/observer.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/common/fee.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/observer/outbound.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/common/fee_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/signer/sign_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/observer/db.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/signer/signer_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

📓 Learnings (2)
zetaclient/chains/bitcoin/observer/event_test.go (1)
Learnt from: ws4charlie
PR: zeta-chain/node#2987
File: pkg/memo/fields_v0_test.go:270-320
Timestamp: 2024-11-12T13:20:12.658Z
Learning: In the `FieldsV0` struct of the `memo` package, `RevertAddress` may be left empty when `CallOnRevert` is set to true.
zetaclient/chains/bitcoin/observer/db.go (1)
Learnt from: ws4charlie
PR: zeta-chain/node#3306
File: zetaclient/chains/bitcoin/observer/db.go:11-25
Timestamp: 2025-01-14T00:09:01.416Z
Learning: In Bitcoin observer, non-critical DB operations (like saving broadcasted transactions) should log errors but not return them to callers, as the errors are already handled appropriately through logging and don't affect the critical in-memory state.
🪛 GitHub Check: codecov/patch
zetaclient/chains/bitcoin/observer/gas_price.go

[warning] 15-34: zetaclient/chains/bitcoin/observer/gas_price.go#L15-L34
Added lines #L15 - L34 were not covered by tests


[warning] 38-41: zetaclient/chains/bitcoin/observer/gas_price.go#L38-L41
Added lines #L38 - L41 were not covered by tests


[warning] 44-51: zetaclient/chains/bitcoin/observer/gas_price.go#L44-L51
Added lines #L44 - L51 were not covered by tests


[warning] 53-53: zetaclient/chains/bitcoin/observer/gas_price.go#L53
Added line #L53 was not covered by tests


[warning] 57-68: zetaclient/chains/bitcoin/observer/gas_price.go#L57-L68
Added lines #L57 - L68 were not covered by tests

zetaclient/chains/bitcoin/client/helpers.go

[warning] 120-123: zetaclient/chains/bitcoin/client/helpers.go#L120-L123
Added lines #L120 - L123 were not covered by tests


[warning] 127-131: zetaclient/chains/bitcoin/client/helpers.go#L127-L131
Added lines #L127 - L131 were not covered by tests


[warning] 133-145: zetaclient/chains/bitcoin/client/helpers.go#L133-L145
Added lines #L133 - L145 were not covered by tests


[warning] 147-147: zetaclient/chains/bitcoin/client/helpers.go#L147
Added line #L147 was not covered by tests

zetaclient/chains/bitcoin/observer/observer.go

[warning] 268-269: zetaclient/chains/bitcoin/observer/observer.go#L268-L269
Added lines #L268 - L269 were not covered by tests

zetaclient/chains/bitcoin/common/fee.go

[warning] 250-250: zetaclient/chains/bitcoin/common/fee.go#L250
Added line #L250 was not covered by tests


[warning] 290-290: zetaclient/chains/bitcoin/common/fee.go#L290
Added line #L290 was not covered by tests

zetaclient/chains/bitcoin/observer/outbound.go

[warning] 38-41: zetaclient/chains/bitcoin/observer/outbound.go#L38-L41
Added lines #L38 - L41 were not covered by tests


[warning] 43-46: zetaclient/chains/bitcoin/observer/outbound.go#L43-L46
Added lines #L43 - L46 were not covered by tests


[warning] 49-50: zetaclient/chains/bitcoin/observer/outbound.go#L49-L50
Added lines #L49 - L50 were not covered by tests


[warning] 53-53: zetaclient/chains/bitcoin/observer/outbound.go#L53
Added line #L53 was not covered by tests


[warning] 64-66: zetaclient/chains/bitcoin/observer/outbound.go#L64-L66
Added lines #L64 - L66 were not covered by tests


[warning] 88-95: zetaclient/chains/bitcoin/observer/outbound.go#L88-L95
Added lines #L88 - L95 were not covered by tests


[warning] 97-97: zetaclient/chains/bitcoin/observer/outbound.go#L97
Added line #L97 was not covered by tests


[warning] 101-101: zetaclient/chains/bitcoin/observer/outbound.go#L101
Added line #L101 was not covered by tests


[warning] 124-126: zetaclient/chains/bitcoin/observer/outbound.go#L124-L126
Added lines #L124 - L126 were not covered by tests


[warning] 143-144: zetaclient/chains/bitcoin/observer/outbound.go#L143-L144
Added lines #L143 - L144 were not covered by tests


[warning] 232-232: zetaclient/chains/bitcoin/observer/outbound.go#L232
Added line #L232 was not covered by tests


[warning] 234-234: zetaclient/chains/bitcoin/observer/outbound.go#L234
Added line #L234 was not covered by tests


[warning] 240-240: zetaclient/chains/bitcoin/observer/outbound.go#L240
Added line #L240 was not covered by tests


[warning] 242-242: zetaclient/chains/bitcoin/observer/outbound.go#L242
Added line #L242 was not covered by tests


[warning] 258-258: zetaclient/chains/bitcoin/observer/outbound.go#L258
Added line #L258 was not covered by tests


[warning] 262-262: zetaclient/chains/bitcoin/observer/outbound.go#L262
Added line #L262 was not covered by tests

zetaclient/chains/bitcoin/observer/db.go

[warning] 22-25: zetaclient/chains/bitcoin/observer/db.go#L22-L25
Added lines #L22 - L25 were not covered by tests


[warning] 61-63: zetaclient/chains/bitcoin/observer/db.go#L61-L63
Added lines #L61 - L63 were not covered by tests

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: start-e2e-test / e2e
🔇 Additional comments (33)
zetaclient/testutils/testdata_naming.go (1)

67-70: LGTM! The function maintains consistency with existing patterns.

The implementation follows the established naming conventions and maintains consistency with other Bitcoin-related filename functions in the codebase.

zetaclient/testutils/mocks/zetacore_client_opts.go (1)

37-46: Well-integrated with existing codebase patterns!

The new method follows the established builder pattern and error handling conventions consistently used throughout the file.

zetaclient/orchestrator/orchestrator.go (2)

411-411: Method naming convention updated for consistency.

The renaming of methods to use "CCTX" instead of "Cctx" improves consistency with the codebase's naming conventions.

Also applies to: 416-416


431-432: Function signatures follow consistent naming pattern.

The renamed functions ScheduleCCTXEVM and ScheduleCCTXSolana maintain consistent parameter ordering and types, which is good for maintainability.

Also applies to: 530-531

zetaclient/chains/bitcoin/observer/inbound_test.go (2)

158-158: LGTM! Test suite initialization updated correctly.

The addition of the empty string parameter for dbPath aligns with the updated test suite initialization pattern.


170-170: LGTM! Explicit string conversion improves type safety.

The addition of .String() ensures consistent string representation of Bitcoin addresses in test data.

zetaclient/chains/bitcoin/observer/observer_test.go (3)

16-16: LGTM!

The addition of the testutils import is appropriate for accessing test constants.


168-168: LGTM!

Using an in-memory database for these tests is the correct approach as it ensures test isolation and performance.

Also applies to: 192-192


281-286: LGTM!

The TSS signer initialization based on chain type is well-structured and uses appropriate test constants.

zetaclient/chains/evm/signer/signer.go (2)

522-523: LGTM! Improved type safety in error handling.

The direct usage of numeric types instead of string conversions enhances type safety and reduces unnecessary conversions.


Line range hint 92-117: Review and implement EIP-1559 support.

The commented code in newTx suggests incomplete implementation of EIP-1559 (dynamic fee transactions). This should be either implemented or the commented code should be removed.

zetaclient/chains/bitcoin/signer/outbound_data.go (1)

103-104: Ensure addition of minRelayFee does not cause an overflow

When adding minRelayFee to feeRate, there's a potential risk of integer overflow if the values are large. Consider implementing a check to ensure that the addition does not exceed the maximum value of int64.

zetaclient/chains/bitcoin/signer/signer.go (1)

75-82: New TSSToPkScript method correctly generates the TSS public key script

The implementation of TSSToPkScript appropriately encapsulates the generation of the pay-to-address script for the TSS public key. This enhances code modularity and reusability.

zetaclient/chains/bitcoin/signer/sign.go (1)

215-220: ⚠️ Potential issue

Validate Previous Output Fetcher Parameters

In SignTx, the txscript.NewTxSigHashes function is called with a CannedPrevOutputFetcher initialized with an empty script and a zero amount. Ensure that the previous output fetcher is correctly initialized with the actual previous outputs' scripts and amounts to generate accurate signature hashes.

Please verify that the previous outputs are correctly fetched and used in the signature hash calculation. If necessary, update the CannedPrevOutputFetcher initialization.

zetaclient/logs/fields.go (1)

12-12: LGTM! Consistent constant definition.

The new FieldOutboundID constant follows the established naming pattern and maintains consistency with other logging field keys.

zetaclient/chains/evm/rpc/rpc_live_test.go (1)

21-21: LGTM! Consistent URL constant definition.

The URLBaseMainnet constant follows the established naming pattern and URL structure.

zetaclient/chains/bitcoin/observer/db.go (1)

12-27: LGTM! Follows established error handling pattern.

The implementation correctly follows the learning that non-critical DB operations should log errors but not return them.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 22-25: zetaclient/chains/bitcoin/observer/db.go#L22-L25
Added lines #L22 - L25 were not covered by tests

x/crosschain/types/revert_options_test.go (1)

52-52: LGTM! Type-safe address handling.

The explicit conversion of Bitcoin address to string format ensures type safety and consistent address handling across the codebase.

zetaclient/zetacore/broadcast.go (1)

162-172: LGTM! Type safety improvements.

The changes enhance type safety by using more appropriate types (uint64 for nonce and int64 for toChain) and update the logging statements accordingly.

zetaclient/chains/bitcoin/client/helpers.go (2)

15-24: LGTM! Well-defined constants.

The constants are appropriately named, documented, and have correct values for Bitcoin fee rate handling.


126-148: Add unit tests and improve error handling.

The function logic is correct, but consider these improvements:

  1. Add unit tests to verify fee rate estimation for various scenarios.
  2. Consider consolidating error messages into constants or using a custom error type for better error handling.
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 127-131: zetaclient/chains/bitcoin/client/helpers.go#L127-L131
Added lines #L127 - L131 were not covered by tests


[warning] 133-145: zetaclient/chains/bitcoin/client/helpers.go#L133-L145
Added lines #L133 - L145 were not covered by tests


[warning] 147-147: zetaclient/chains/bitcoin/client/helpers.go#L147
Added line #L147 was not covered by tests

testutil/sample/crypto.go (2)

95-104: LGTM! Improved return type.

The function now returns a more appropriate type (*btcutil.AddressWitnessPubKeyHash) instead of a string representation.


106-111: LGTM! Well-structured helper function.

The function provides a convenient way to generate payment scripts for test addresses.

zetaclient/chains/bitcoin/signer/outbound_data_test.go (1)

18-241: LGTM! Comprehensive test coverage.

The test suite is well-structured with:

  • Clear test case descriptions
  • Good coverage of edge cases and error scenarios
  • Proper validation of expected outputs
  • Effective use of test helpers and sample data
zetaclient/chains/bitcoin/signer/sign_test.go (1)

24-91: LGTM! Comprehensive test cases for transaction input handling.

The test cases effectively cover:

  • Success scenario with multiple inputs
  • Failure on invalid transaction ID
  • Failure on invalid amount
x/crosschain/types/cctx_test.go (1)

143-143: LGTM! Consistent string representation of Bitcoin addresses.

The change ensures type safety by explicitly converting the Bitcoin address to its string representation.

zetaclient/chains/bitcoin/common/fee.go (1)

22-32: LGTM! Well-documented constants with clear purpose.

The constants are well-organized and properly documented with their respective byte sizes and purposes.

zetaclient/chains/bitcoin/observer/event_test.go (1)

35-35: LGTM! Consistent address type handling.

The changes ensure consistent string representation of Bitcoin addresses across test cases.

Also applies to: 252-252, 403-403

zetaclient/chains/bitcoin/client/client_test.go (1)

140-140: LGTM!

The changes correctly update the test assertions to:

  1. Include depositor fee in transaction value validation
  2. Use a more focused block range for fee rate testing

Also applies to: 335-335

zetaclient/chains/bitcoin/common/fee_test.go (1)

186-189: LGTM!

The changes successfully:

  1. Add test coverage for zero UTXO scenarios
  2. Update type signatures from uint64 to int64 consistently
  3. Maintain comprehensive test coverage for all address types

Also applies to: 201-203, 225-227, 249-253, 270-325

zetaclient/testutils/mocks/bitcoin_client.go (1)

360-386: LGTM!

The auto-generated mock implementation for GetEstimatedFeeRate correctly follows the established patterns for:

  • Parameter handling
  • Return value management
  • Error scenarios
zetaclient/chains/bitcoin/observer/observer.go (1)

251-255: Function IsTSSTransaction implementation is optimal

The IsTSSTransaction method efficiently checks whether a transaction was sent by the TSS address by looking up the transaction ID in the tssOutboundHashes map. The implementation is clear and adheres to best practices.

zetaclient/chains/bitcoin/observer/outbound.go (1)

24-28: ⚠️ Potential issue

Set minTxConfirmations to a secure value for production

The constant minTxConfirmations is currently set to 0, allowing transactions with zero confirmations to be considered valid. This poses a significant security risk in a production environment, as unconfirmed transactions are vulnerable to double-spending attacks. It is advisable to set minTxConfirmations to a safer value, such as 1 or higher, to ensure transactions are confirmed on the blockchain before being accepted.

Apply this diff to set a secure confirmation threshold:

-	minTxConfirmations = 0
+	minTxConfirmations = 1
⛔ Skipped due to learnings
Learnt from: ws4charlie
PR: zeta-chain/node#3306
File: zetaclient/chains/bitcoin/observer/outbound.go:28-32
Timestamp: 2025-01-13T23:51:09.334Z
Learning: In Bitcoin observer, `minTxConfirmations` is set to 0 to allow observing mempool transactions without waiting for block confirmations, which is necessary due to Bitcoin's 10-minute block time. This is a deliberate design choice despite potential security implications, as other safety checks are in place through TSS validation.

zetaclient/chains/bitcoin/observer/utxos.go Show resolved Hide resolved
zetaclient/chains/bitcoin/observer/utxos.go Show resolved Hide resolved
zetaclient/chains/bitcoin/signer/sign.go Show resolved Hide resolved
zetaclient/chains/bitcoin/client/helpers.go Outdated Show resolved Hide resolved
zetaclient/chains/bitcoin/common/fee.go Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🔭 Outside diff range comments (1)
zetaclient/chains/bitcoin/common/fee.go (1)

Add test coverage for fee rate calculation.

The function GetRecentFeeRate lacks test coverage for critical paths:

  • Mainnet rejection logic
  • Block count error handling
  • Fee rate calculations from recent blocks
  • Default testnet fee rate fallback

Please add unit tests to verify these scenarios as originally suggested.

🔗 Analysis chain

Line range hint 250-290: Add test coverage for fee rate calculation.

This function lacks test coverage which is critical as it handles fee rate calculations. Please add unit tests to verify:

  1. Mainnet rejection
  2. Block count error handling
  3. Fee rate calculation for various scenarios
  4. Default testnet fee rate fallback
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify test coverage for GetRecentFeeRate function
ast-grep --pattern 'func TestGetRecentFeeRate'

Length of output: 48


Script:

#!/bin/bash
# Find test files in the bitcoin/common directory
fd ".*_test.go$" zetaclient/chains/bitcoin/common

# Search for any fee-related test functions
rg "func Test.*Fee.*" zetaclient/chains/bitcoin/common -A 5

# Search for any usage of GetRecentFeeRate in test files
rg "GetRecentFeeRate" zetaclient/chains/bitcoin/common --type go

Length of output: 630


Script:

#!/bin/bash
# Examine the content of fee_test.go
cat zetaclient/chains/bitcoin/common/fee_test.go

Length of output: 18019

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 250-250: zetaclient/chains/bitcoin/common/fee.go#L250
Added line #L250 was not covered by tests

🧹 Nitpick comments (31)
zetaclient/chains/bitcoin/signer/signer_test.go (4)

1-34: Consider grouping imports for better organization.

Consider organizing imports into logical groups:

  1. Standard library
  2. External dependencies
  3. Internal packages
 import (
+	// Standard library
 	"context"
 	"encoding/hex"
 	"testing"
 
+	// External dependencies
 	"github.com/btcsuite/btcd/btcec/v2"
 	"github.com/btcsuite/btcd/btcec/v2/ecdsa"
 	"github.com/btcsuite/btcd/btcjson"
 	"github.com/btcsuite/btcd/btcutil"
 	"github.com/btcsuite/btcd/chaincfg"
 	"github.com/btcsuite/btcd/chaincfg/chainhash"
 	"github.com/btcsuite/btcd/txscript"
 	"github.com/btcsuite/btcd/wire"
 	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/rs/zerolog"
 	"github.com/stretchr/testify/mock"
 	"github.com/stretchr/testify/require"
 
+	// Internal packages
 	"github.com/zeta-chain/node/pkg/chains"
 	crosschaintypes "github.com/zeta-chain/node/x/crosschain/types"
 	observertypes "github.com/zeta-chain/node/x/observer/types"
 	"github.com/zeta-chain/node/zetaclient/chains/base"
 	"github.com/zeta-chain/node/zetaclient/chains/bitcoin/observer"
 	"github.com/zeta-chain/node/zetaclient/chains/bitcoin/signer"
 	"github.com/zeta-chain/node/zetaclient/config"
 	zctx "github.com/zeta-chain/node/zetaclient/context"
 	"github.com/zeta-chain/node/zetaclient/db"
 	"github.com/zeta-chain/node/zetaclient/keys"
 	"github.com/zeta-chain/node/zetaclient/metrics"
 	"github.com/zeta-chain/node/zetaclient/outboundprocessor"
 	"github.com/zeta-chain/node/zetaclient/testutils"
 	"github.com/zeta-chain/node/zetaclient/testutils/mocks"
 )

37-38: Consider using a more robust way to locate test data.

Using a relative path for test data directory could be fragile if the test file is moved. Consider using go:embed or filepath.Join() with a base directory determined at runtime.


Line range hint 173-238: Consider extracting test constants for better maintainability.

The hardcoded private key and test values in P2PH and P2WPH tests should be moved to test constants or a separate test data file.

+const (
+    testPrivKeyHex = "22a47fa09a223f2aa079edf85a7c2d4f8720ee63e502ee2869afab7de234b80c"
+    testAmount     = 100000000 // 1 BTC in satoshis
+)

Also applies to: 241-334


337-398: Enhance helper function documentation.

While the helper functions are well-implemented, consider adding more detailed documentation explaining:

  • Expected inputs and outputs
  • Any side effects
  • Usage examples
zetaclient/chains/bitcoin/observer/observer_test.go (2)

205-215: Enhance test coverage with additional edge cases.

Consider adding test cases for:

  • Setting maximum uint64 value
  • Setting to zero after non-zero value
  • Concurrent access if the nonce is accessed by multiple goroutines

298-300: Enhance test logger configuration.

The current logger setup could be improved to:

  1. Set a consistent log level for tests
  2. Configure sampling for high-volume test logs
-testLogger := zerolog.New(zerolog.NewTestWriter(t))
+testLogger := zerolog.New(zerolog.NewTestWriter(t)).
+  Level(zerolog.InfoLevel).
+  Sample(&zerolog.BasicSampler{N: 10})
 logger := base.Logger{Std: testLogger, Compliance: testLogger}
zetaclient/zetacore/broadcast_test.go (1)

34-34: Consider using meaningful test values and adding edge cases.

While the test correctly uses the new parameter types, consider:

  1. Using meaningful values that reflect real scenarios (e.g., actual nonce values)
  2. Adding edge cases like MAX_UINT64 for nonce and negative chain IDs
-		retry, report := HandleBroadcastError(input, 100, 1, "")
+		testCases := []struct {
+			name         string
+			err          error
+			nonce        uint64
+			toChain      int64
+			outboundHash string
+			wantRetry    bool
+			wantReport   bool
+		}{
+			{
+				name:    "nonce too low with typical value",
+				err:     errors.New("nonce too low"),
+				nonce:   1000,
+				toChain: 1,
+				wantRetry: false,
+				wantReport: false,
+			},
+			{
+				name:    "edge case - max nonce",
+				err:     errors.New("nonce too low"),
+				nonce:   ^uint64(0),
+				toChain: -1,
+				wantRetry: false,
+				wantReport: false,
+			},
+		}
zetaclient/zetacore/broadcast.go (1)

162-162: Enhance function documentation with return value descriptions.

The function comment should explain the meaning of the boolean return values and when they are set.

-// HandleBroadcastError returns whether to retry in a few seconds, and whether to report via AddOutboundTracker
-// returns (bool retry, bool report)
+// HandleBroadcastError handles broadcast errors and determines the next action.
+// Parameters:
+//   - err: The error encountered during broadcast
+//   - nonce: The transaction nonce (sequence number)
+//   - toChain: The destination chain ID
+//   - outboundHash: The hash of the outbound transaction
+// Returns:
+//   - retry: true if the broadcast should be retried
+//   - report: true if the error should be reported via AddOutboundTracker
zetaclient/chains/bitcoin/signer/outbound_data.go (3)

21-49: Consider grouping related fields and adding validation tags.

The struct fields could be organized into logical groups using comments, and validation tags could be added for better data integrity:

 type OutboundData struct {
+    // Transaction identifiers
     chainID int64
+    nonce   uint64
+    height  uint64
 
+    // Transaction details
     to     btcutil.Address
     amount float64    `validate:"gte=0"`
     feeRate int64     `validate:"gt=0"`
     txSize  int64     `validate:"gt=0"`
 
+    // Internal state
     amountSats int64
     cancelTx   bool
-    nonce      uint64
-    height     uint64
 }

51-137: Extract validation logic into separate functions.

The constructor handles multiple responsibilities. Consider extracting validation logic into separate functions for better maintainability:

+func validateInputs(cctx *types.CrossChainTx) error {
+    if cctx == nil {
+        return errors.New("cctx is nil")
+    }
+    if cctx.InboundParams.CoinType != coin.CoinType_Gas {
+        return errors.New("can only send gas token to a Bitcoin network")
+    }
+    return nil
+}

+func validateFeeRate(params *types.OutboundTxParams) (int64, error) {
+    feeRate, err := strconv.ParseInt(params.GasPrice, 10, 64)
+    if err != nil || feeRate <= 0 {
+        return 0, fmt.Errorf("invalid fee rate %s", params.GasPrice)
+    }
+    return feeRate, nil
+}

 func NewOutboundData(...) (*OutboundData, error) {
-    if cctx == nil {
-        return nil, errors.New("cctx is nil")
-    }
+    if err := validateInputs(cctx); err != nil {
+        return nil, err
+    }
     params := cctx.GetCurrentOutboundParam()
 
-    if cctx.InboundParams.CoinType != coin.CoinType_Gas {
-        return nil, errors.New("can only send gas token to a Bitcoin network")
-    }
-
-    feeRate, err := strconv.ParseInt(params.GasPrice, 10, 64)
-    if err != nil || feeRate <= 0 {
-        return nil, fmt.Errorf("invalid fee rate %s", params.GasPrice)
-    }
+    feeRate, err := validateFeeRate(params)
+    if err != nil {
+        return nil, err
+    }

92-93: Consider using btcutil.Amount for Bitcoin amount conversions.

The manual conversion to BTC and satoshis could be replaced with btcutil.Amount for safer conversions:

-amount := float64(params.Amount.Uint64()) / 1e8
-amountSats := params.Amount.BigInt().Int64()
+amountSats := params.Amount.BigInt().Int64()
+amount := btcutil.Amount(amountSats).ToBTC()
zetaclient/chains/bitcoin/signer/outbound_data_test.go (2)

18-241: Consider adding sub-benchmarks and edge cases.

The test coverage is comprehensive, but consider these improvements:

  1. Add benchmarks for performance-critical paths:
func BenchmarkNewOutboundData(b *testing.B) {
    // Setup test data
    chain := chains.BitcoinMainnet
    receiver, _ := chains.DecodeBtcAddress("bc1qaxf82vyzy8y80v000e7t64gpten7gawewzu42y", chain.ChainId)
    
    b.Run("successful_creation", func(b *testing.B) {
        cctx := sample.CrossChainTx(b, "0x123")
        // Setup cctx...
        
        b.ResetTimer()
        for i := 0; i < b.N; i++ {
            NewOutboundData(cctx, chain.ChainId, 101, 0.00001, log.Logger, log.Logger)
        }
    })
}
  1. Add edge cases:
  • Maximum possible amount
  • Maximum possible gas limit (just below MaxInt64)
  • Empty receiver address
  • Zero height

231-231: Consider mocking the logger for cleaner tests.

The test is using the global logger. Consider creating a mock or test logger:

-outboundData, err := NewOutboundData(tt.cctx, tt.chainID, tt.height, tt.minRelayFee, log.Logger, log.Logger)
+testLogger := zerolog.New(ioutil.Discard)
+outboundData, err := NewOutboundData(tt.cctx, tt.chainID, tt.height, tt.minRelayFee, testLogger, testLogger)
zetaclient/chains/bitcoin/common/fee.go (1)

77-84: Improve error handling for invalid input.

Consider returning an error for negative input values to make the validation more explicit.

 func EstimateOutboundSize(numInputs int64, payees []btcutil.Address) (int64, error) {
+    if numInputs < 0 {
+        return 0, fmt.Errorf("negative number of inputs: %d", numInputs)
+    }
     if numInputs <= 0 {
         return 0, nil
     }
zetaclient/chains/bitcoin/common/fee_test.go (1)

249-252: Consider using integer arithmetic for error tolerance.

The current floating-point calculation could lead to precision issues. Consider using integer arithmetic:

-vError := int64(
-    0.25 + float64(x)/4,
-) // 1st witness incurs 0.25 more vByte error than others (which incurs 1/4 vByte per witness)
+vError := (x + 1) / 4 // Integer division: each witness contributes 1/4 vByte error
zetaclient/chains/bitcoin/observer/utxos.go (1)

44-44: Enhance error message by including the underlying error.

Including the original error message in the returned error can improve debugging and provide more context about the failure.

Apply this diff to include the underlying error:

-		return fmt.Errorf("error getting bitcoin tss address")
+		return fmt.Errorf("error getting bitcoin TSS address: %v", err)
zetaclient/chains/bitcoin/observer/observer.go (1)

268-269: Add unit tests for isNodeEnabled method to improve test coverage.

The isNodeEnabled method is currently not covered by any tests. Adding unit tests will help ensure the method behaves as expected and prevent potential issues in the future.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 268-269: zetaclient/chains/bitcoin/observer/observer.go#L268-L269
Added lines #L268 - L269 were not covered by tests

zetaclient/chains/bitcoin/observer/outbound.go (1)

74-98: Add unit tests for TryIncludeOutbound method to ensure reliability.

The TryIncludeOutbound method plays a crucial role in including outbound transactions but lacks test coverage. Implementing unit tests will help validate its functionality and maintain code quality.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 88-95: zetaclient/chains/bitcoin/observer/outbound.go#L88-L95
Added lines #L88 - L95 were not covered by tests


[warning] 97-97: zetaclient/chains/bitcoin/observer/outbound.go#L97
Added line #L97 was not covered by tests

zetaclient/chains/evm/rpc/rpc_live_test.go (1)

65-73: Enhance test robustness and resource management.

While the basic test functionality is present, consider these improvements:

  1. Add client connection cleanup using defer client.Close()
  2. Add timeout to context
  3. Add more comprehensive gas price validations
 func LiveTest_SuggestGasPrice(t *testing.T) {
 	client, err := ethclient.Dial(URLBaseMainnet)
 	require.NoError(t, err)
+	defer client.Close()
 
-	ctx := context.Background()
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	defer cancel()
 
 	gasPrice, err := client.SuggestGasPrice(ctx)
 	require.NoError(t, err)
-	require.True(t, gasPrice.Cmp(big.NewInt(0)) > 0)
+	require.True(t, gasPrice.Cmp(big.NewInt(0)) > 0, "gas price should be positive")
+	require.True(t, gasPrice.BitLen() <= 256, "gas price should not exceed 256 bits")
 }
zetaclient/chains/bitcoin/observer/gas_price.go (1)

56-70: Add error handling for unsupported network types.

The error handling for unsupported network types could be more informative.

 func (ob *Observer) specialHandleFeeRate(ctx context.Context) (int64, error) {
     switch ob.Chain().NetworkType {
     // ... existing cases ...
     default:
-        return 0, fmt.Errorf(" unsupported bitcoin network type %d", ob.Chain().NetworkType)
+        return 0, fmt.Errorf("unsupported bitcoin network type %d for fee rate estimation", ob.Chain().NetworkType)
     }
 }
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 57-68: zetaclient/chains/bitcoin/observer/gas_price.go#L57-L68
Added lines #L57 - L68 were not covered by tests

zetaclient/testutils/mocks/zetacore_client_opts.go (1)

37-46: Consider using specific mock matchers.

While the implementation is functional, using specific matchers would make the mock expectations more precise.

 func (_m *ZetacoreClient) WithPostOutboundTracker(zetaTxHash string) *ZetacoreClient {
-    on := _m.On("PostOutboundTracker", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Maybe()
+    on := _m.On(
+        "PostOutboundTracker",
+        mock.AnythingOfType("*context.Context"),
+        mock.AnythingOfType("string"),  // outboundID
+        mock.AnythingOfType("string"),  // txHash
+        mock.AnythingOfType("uint64"),  // blockHeight
+    ).Maybe()
     if zetaTxHash != "" {
         on.Return(zetaTxHash, nil)
     } else {
         on.Return("", errSomethingIsWrong)
     }
     return _m
 }
zetaclient/chains/bitcoin/observer/db.go (1)

29-55: Consider adding context timeout for RPC calls.

While the implementation is solid, RPC calls to Bitcoin nodes should have appropriate timeouts to prevent hanging in case of network issues.

 func (ob *Observer) LoadLastBlockScanned(ctx context.Context) error {
+    // Add timeout for RPC calls
+    ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
+    defer cancel()
     err := ob.Observer.LoadLastBlockScanned(ob.Logger().Chain)
zetaclient/chains/bitcoin/observer/db_test.go (2)

17-38: Add test case for concurrent access.

Consider adding a test case that verifies thread safety by simulating concurrent access to SaveBroadcastedTx.

t.Run("should handle concurrent saves", func(t *testing.T) {
    ob := newTestSuite(t, chains.BitcoinMainnet, "")
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(nonce uint64) {
            defer wg.Done()
            txHash := sample.BtcHash().String()
            ob.SaveBroadcastedTx(txHash, nonce)
        }(uint64(i))
    }
    wg.Wait()
})

60-62: Use t.Setenv instead of os.Setenv in tests.

Using t.Setenv is preferred in tests as it automatically handles cleanup.

-        os.Setenv(envvar, "invalid")
-        defer os.Unsetenv(envvar)
+        t.Setenv(envvar, "invalid")
zetaclient/chains/bitcoin/signer/sign_test.go (3)

24-91: Consider adding more edge cases to the test suite.

The test suite follows good practices with table-driven tests. Consider adding these edge cases:

  1. Maximum number of inputs
  2. Zero amount inputs
  3. Duplicate transaction IDs

Would you like me to help generate these additional test cases?


93-257: Avoid hardcoding Bitcoin addresses in tests.

Replace the hardcoded Bitcoin address with a dynamically generated one using the existing test utilities:

-    receiver := "bc1qaxf82vyzy8y80v000e7t64gpten7gawewzu42y"
+    receiver := sample.BtcAddressP2WPKH(t, chains.BitcoinMainnet.Params).String()

259-326: Add error cases to the test suite.

The test suite only covers the happy path. Consider adding these test cases:

  1. Invalid input amounts
  2. Missing witness data
  3. Invalid signature
  4. Context cancellation

Would you like me to help generate these error test cases?

zetaclient/testutils/testdata.go (1)

120-126: LGTM! Consider adding documentation.

The function implementation is clean and follows the established patterns. Consider adding a doc comment to describe the expected file format and location.

Add this documentation above the function:

// LoadBTCTransaction loads a Bitcoin transaction from a JSON file in the testdata directory.
// The file should contain a serialized btcjson.GetTransactionResult object.
zetaclient/chains/bitcoin/signer/signer.go (3)

168-177: Optimize Retry Logic in BroadcastOutbound

In the BroadcastOutbound function, the retry loop sleeps before the first broadcast attempt, causing unnecessary delay. Modify the loop to attempt broadcasting immediately and sleep only after a failed attempt.

Proposed change:

-    backOff := broadcastBackoff
-    for i := 0; i < broadcastRetries; i++ {
-        time.Sleep(backOff)
+    for i := 0; i < broadcastRetries; i++ {
         // broadcast tx
         err := signer.Broadcast(ctx, tx)
         if err != nil {
             logger.Warn().Err(err).Fields(lf).Msgf("broadcasting Bitcoin outbound, retry %d", i)
+            time.Sleep(backOff)
             backOff *= 2
             continue
         }
         logger.Info().Fields(lf).Msg("broadcasted Bitcoin outbound successfully")
         // successful broadcast; no need to retry
         break
     }

168-200: Add Logging for Failed Broadcast Attempts

If the broadcast fails after all retries in BroadcastOutbound, there is no log indicating the final failure. Add a log message after the retries are exhausted to inform that broadcasting was unsuccessful.

Add after the loop:

if i == broadcastRetries {
    logger.Error().Fields(lf).Msg("Failed to broadcast Bitcoin outbound after maximum retries")
}

119-119: Correct Logging Message Grammar

The error message should be corrected for proper grammar.

Change:

-    logger.Error().Err(err).Msgf("failed get bitcoin network info")
+    logger.Error().Err(err).Msg("failed to get Bitcoin network info")
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 078dbef and 2481654.

📒 Files selected for processing (39)
  • changelog.md (1 hunks)
  • testutil/sample/crypto.go (2 hunks)
  • x/crosschain/types/cctx_test.go (1 hunks)
  • x/crosschain/types/revert_options_test.go (1 hunks)
  • zetaclient/chains/bitcoin/client/client_test.go (2 hunks)
  • zetaclient/chains/bitcoin/client/helpers.go (3 hunks)
  • zetaclient/chains/bitcoin/client/mockgen.go (1 hunks)
  • zetaclient/chains/bitcoin/common/fee.go (7 hunks)
  • zetaclient/chains/bitcoin/common/fee_test.go (11 hunks)
  • zetaclient/chains/bitcoin/observer/db.go (1 hunks)
  • zetaclient/chains/bitcoin/observer/db_test.go (1 hunks)
  • zetaclient/chains/bitcoin/observer/event_test.go (5 hunks)
  • zetaclient/chains/bitcoin/observer/gas_price.go (1 hunks)
  • zetaclient/chains/bitcoin/observer/inbound_test.go (2 hunks)
  • zetaclient/chains/bitcoin/observer/observer.go (5 hunks)
  • zetaclient/chains/bitcoin/observer/observer_test.go (5 hunks)
  • zetaclient/chains/bitcoin/observer/outbound.go (6 hunks)
  • zetaclient/chains/bitcoin/observer/outbound_test.go (7 hunks)
  • zetaclient/chains/bitcoin/observer/utxos.go (1 hunks)
  • zetaclient/chains/bitcoin/signer/outbound_data.go (1 hunks)
  • zetaclient/chains/bitcoin/signer/outbound_data_test.go (1 hunks)
  • zetaclient/chains/bitcoin/signer/sign.go (1 hunks)
  • zetaclient/chains/bitcoin/signer/sign_test.go (1 hunks)
  • zetaclient/chains/bitcoin/signer/signer.go (4 hunks)
  • zetaclient/chains/bitcoin/signer/signer_test.go (10 hunks)
  • zetaclient/chains/evm/observer/observer_test.go (0 hunks)
  • zetaclient/chains/evm/rpc/rpc_live_test.go (4 hunks)
  • zetaclient/chains/evm/signer/signer.go (1 hunks)
  • zetaclient/logs/fields.go (1 hunks)
  • zetaclient/orchestrator/orchestrator.go (10 hunks)
  • zetaclient/orchestrator/v2_bootstrap.go (0 hunks)
  • zetaclient/testdata/btc/chain_8332_msgtx_030cd813443f7b70cc6d8a544d320c6d8465e4528fc0f3410b599dc0b26753a0.json (1 hunks)
  • zetaclient/testdata/btc/chain_8332_tx_030cd813443f7b70cc6d8a544d320c6d8465e4528fc0f3410b599dc0b26753a0.json (1 hunks)
  • zetaclient/testutils/mocks/bitcoin_client.go (1 hunks)
  • zetaclient/testutils/mocks/zetacore_client_opts.go (1 hunks)
  • zetaclient/testutils/testdata.go (1 hunks)
  • zetaclient/testutils/testdata_naming.go (1 hunks)
  • zetaclient/zetacore/broadcast.go (2 hunks)
  • zetaclient/zetacore/broadcast_test.go (1 hunks)
💤 Files with no reviewable changes (2)
  • zetaclient/orchestrator/v2_bootstrap.go
  • zetaclient/chains/evm/observer/observer_test.go
✅ Files skipped from review due to trivial changes (3)
  • zetaclient/testdata/btc/chain_8332_tx_030cd813443f7b70cc6d8a544d320c6d8465e4528fc0f3410b599dc0b26753a0.json
  • zetaclient/testdata/btc/chain_8332_msgtx_030cd813443f7b70cc6d8a544d320c6d8465e4528fc0f3410b599dc0b26753a0.json
  • zetaclient/orchestrator/orchestrator.go
🧰 Additional context used
📓 Path-based instructions (33)
zetaclient/logs/fields.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/testutils/testdata_naming.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/zetacore/broadcast_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/testutils/testdata.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/evm/signer/signer.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

x/crosschain/types/revert_options_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/client/client_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/observer/gas_price.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/zetacore/broadcast.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/client/mockgen.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/signer/outbound_data.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

testutil/sample/crypto.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/testutils/mocks/zetacore_client_opts.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/observer/inbound_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/client/helpers.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

x/crosschain/types/cctx_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/signer/outbound_data_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/evm/rpc/rpc_live_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/signer/sign_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/observer/observer_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/observer/db.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/testutils/mocks/bitcoin_client.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/observer/db_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/observer/utxos.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/observer/observer.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/signer/sign.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/common/fee_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/signer/signer.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/observer/event_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/observer/outbound_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/signer/signer_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/observer/outbound.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

zetaclient/chains/bitcoin/common/fee.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

📓 Learnings (4)
zetaclient/chains/bitcoin/client/client_test.go (1)
Learnt from: ws4charlie
PR: zeta-chain/node#2899
File: zetaclient/chains/bitcoin/observer/inbound.go:366-371
Timestamp: 2024-11-12T13:20:12.658Z
Learning: The `bitcoin.CalcDepositorFee` function is covered by live tests.
zetaclient/chains/bitcoin/signer/outbound_data.go (1)
Learnt from: ws4charlie
PR: zeta-chain/node#3306
File: zetaclient/chains/bitcoin/signer/sign.go:155-211
Timestamp: 2025-01-13T23:23:35.853Z
Learning: Amount validation for Bitcoin outbound transactions, including checks for gas price, recipient address, and dust threshold, is performed in NewOutboundData before the transaction signing process begins.
zetaclient/chains/bitcoin/observer/db.go (1)
Learnt from: ws4charlie
PR: zeta-chain/node#3306
File: zetaclient/chains/bitcoin/observer/db.go:11-25
Timestamp: 2025-01-14T00:09:01.416Z
Learning: In Bitcoin observer, non-critical DB operations (like saving broadcasted transactions) should log errors but not return them to callers, as the errors are already handled appropriately through logging and don't affect the critical in-memory state.
zetaclient/chains/bitcoin/observer/event_test.go (1)
Learnt from: ws4charlie
PR: zeta-chain/node#2987
File: pkg/memo/fields_v0_test.go:270-320
Timestamp: 2024-11-12T13:20:12.658Z
Learning: In the `FieldsV0` struct of the `memo` package, `RevertAddress` may be left empty when `CallOnRevert` is set to true.
🪛 GitHub Check: codecov/patch
zetaclient/chains/bitcoin/observer/gas_price.go

[warning] 15-34: zetaclient/chains/bitcoin/observer/gas_price.go#L15-L34
Added lines #L15 - L34 were not covered by tests


[warning] 38-41: zetaclient/chains/bitcoin/observer/gas_price.go#L38-L41
Added lines #L38 - L41 were not covered by tests


[warning] 44-51: zetaclient/chains/bitcoin/observer/gas_price.go#L44-L51
Added lines #L44 - L51 were not covered by tests


[warning] 53-53: zetaclient/chains/bitcoin/observer/gas_price.go#L53
Added line #L53 was not covered by tests


[warning] 57-68: zetaclient/chains/bitcoin/observer/gas_price.go#L57-L68
Added lines #L57 - L68 were not covered by tests

zetaclient/chains/bitcoin/client/helpers.go

[warning] 120-123: zetaclient/chains/bitcoin/client/helpers.go#L120-L123
Added lines #L120 - L123 were not covered by tests


[warning] 127-131: zetaclient/chains/bitcoin/client/helpers.go#L127-L131
Added lines #L127 - L131 were not covered by tests


[warning] 133-145: zetaclient/chains/bitcoin/client/helpers.go#L133-L145
Added lines #L133 - L145 were not covered by tests


[warning] 147-147: zetaclient/chains/bitcoin/client/helpers.go#L147
Added line #L147 was not covered by tests

zetaclient/chains/bitcoin/observer/db.go

[warning] 22-25: zetaclient/chains/bitcoin/observer/db.go#L22-L25
Added lines #L22 - L25 were not covered by tests


[warning] 61-63: zetaclient/chains/bitcoin/observer/db.go#L61-L63
Added lines #L61 - L63 were not covered by tests

zetaclient/chains/bitcoin/observer/observer.go

[warning] 268-269: zetaclient/chains/bitcoin/observer/observer.go#L268-L269
Added lines #L268 - L269 were not covered by tests

zetaclient/chains/bitcoin/observer/outbound.go

[warning] 38-41: zetaclient/chains/bitcoin/observer/outbound.go#L38-L41
Added lines #L38 - L41 were not covered by tests


[warning] 43-46: zetaclient/chains/bitcoin/observer/outbound.go#L43-L46
Added lines #L43 - L46 were not covered by tests


[warning] 49-50: zetaclient/chains/bitcoin/observer/outbound.go#L49-L50
Added lines #L49 - L50 were not covered by tests


[warning] 53-53: zetaclient/chains/bitcoin/observer/outbound.go#L53
Added line #L53 was not covered by tests


[warning] 64-66: zetaclient/chains/bitcoin/observer/outbound.go#L64-L66
Added lines #L64 - L66 were not covered by tests


[warning] 88-95: zetaclient/chains/bitcoin/observer/outbound.go#L88-L95
Added lines #L88 - L95 were not covered by tests


[warning] 97-97: zetaclient/chains/bitcoin/observer/outbound.go#L97
Added line #L97 was not covered by tests


[warning] 101-101: zetaclient/chains/bitcoin/observer/outbound.go#L101
Added line #L101 was not covered by tests


[warning] 124-126: zetaclient/chains/bitcoin/observer/outbound.go#L124-L126
Added lines #L124 - L126 were not covered by tests


[warning] 143-144: zetaclient/chains/bitcoin/observer/outbound.go#L143-L144
Added lines #L143 - L144 were not covered by tests


[warning] 232-232: zetaclient/chains/bitcoin/observer/outbound.go#L232
Added line #L232 was not covered by tests


[warning] 234-234: zetaclient/chains/bitcoin/observer/outbound.go#L234
Added line #L234 was not covered by tests


[warning] 240-240: zetaclient/chains/bitcoin/observer/outbound.go#L240
Added line #L240 was not covered by tests


[warning] 242-242: zetaclient/chains/bitcoin/observer/outbound.go#L242
Added line #L242 was not covered by tests


[warning] 258-258: zetaclient/chains/bitcoin/observer/outbound.go#L258
Added line #L258 was not covered by tests


[warning] 262-262: zetaclient/chains/bitcoin/observer/outbound.go#L262
Added line #L262 was not covered by tests

zetaclient/chains/bitcoin/common/fee.go

[warning] 250-250: zetaclient/chains/bitcoin/common/fee.go#L250
Added line #L250 was not covered by tests


[warning] 290-290: zetaclient/chains/bitcoin/common/fee.go#L290
Added line #L290 was not covered by tests

🔇 Additional comments (26)
zetaclient/chains/bitcoin/signer/signer_test.go (2)

40-83: LGTM! Well-structured test suite setup.

The test suite setup is well-organized with proper mocking of dependencies and clear initialization.


97-170: LGTM! Comprehensive test cases for BroadcastOutbound.

The test cases cover important scenarios including RBF and failure cases.

zetaclient/zetacore/broadcast.go (1)

169-172: LGTM! Well-structured logging implementation.

The logging improvements are excellent:

  • Uses proper field types for type safety
  • Adds method field for better tracing
  • Maintains consistency across error cases
zetaclient/chains/bitcoin/common/fee.go (1)

22-32: LGTM! Well-documented constants with clear purpose.

The constants are properly documented with their respective byte sizes and the type conversion to int64 is consistent with the function signature changes.

zetaclient/chains/bitcoin/common/fee_test.go (1)

270-270: LGTM! Consistent use of require.Zero for nil address tests.

The test assertions are clear and consistent across all address types, improving test readability.

Also applies to: 281-281, 292-292, 303-303, 314-314, 325-325

zetaclient/chains/bitcoin/observer/outbound.go (1)

25-28: ⚠️ Potential issue

Set minTxConfirmations to a safer default value for production.

Having minTxConfirmations set to 0 may allow transactions with zero confirmations to be considered valid, which can pose security risks. It's advisable to set this value to at least 1 to ensure that only transactions with confirmed blocks are processed.

Apply this diff to update the confirmation threshold:

 const (
     // minTxConfirmations is the minimum confirmations for a Bitcoin tx to be considered valid by the observer
     // Note: please change this value to 1 to be able to run the Bitcoin E2E RBF test
-	minTxConfirmations = 0
+	minTxConfirmations = 1
 )
⛔ Skipped due to learnings
Learnt from: ws4charlie
PR: zeta-chain/node#3306
File: zetaclient/chains/bitcoin/observer/outbound.go:28-32
Timestamp: 2025-01-13T23:51:09.334Z
Learning: In Bitcoin observer, `minTxConfirmations` is set to 0 to allow observing mempool transactions without waiting for block confirmations, which is necessary due to Bitcoin's 10-minute block time. This is a deliberate design choice despite potential security implications, as other safety checks are in place through TSS validation.
zetaclient/logs/fields.go (1)

12-12: LGTM: New field constant follows conventions.

The addition of FieldOutboundID aligns with existing field naming patterns and supports the Bitcoin RBF integration objectives.

zetaclient/chains/evm/rpc/rpc_live_test.go (1)

21-21: LGTM: Base mainnet URL constant added.

The constant follows the existing URL naming pattern.

zetaclient/chains/bitcoin/observer/db.go (1)

12-27: LGTM! Thread-safe implementation with proper error handling.

The implementation correctly uses mutex for thread safety and follows the established pattern of logging DB errors without returning them.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 22-25: zetaclient/chains/bitcoin/observer/db.go#L22-L25
Added lines #L22 - L25 were not covered by tests

x/crosschain/types/revert_options_test.go (1)

52-52: LGTM! Improved type safety.

The explicit conversion to string using .String() method improves type safety and clarity.

zetaclient/chains/bitcoin/client/mockgen.go (1)

48-48: LGTM! Clean interface extension.

The new method follows the existing pattern and has a clear, well-defined signature.

zetaclient/chains/bitcoin/observer/db_test.go (1)

94-120: LGTM! Comprehensive persistence testing.

The test effectively verifies that transaction data persists across different observer instances.

zetaclient/chains/bitcoin/client/helpers.go (2)

119-124: Add unit tests for fee rate conversion.

The function logic looks correct, but it lacks test coverage. Please add unit tests to verify the conversion from BTC/KB to sat/vB.

Would you like me to help generate comprehensive test cases for this function?

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 120-123: zetaclient/chains/bitcoin/client/helpers.go#L120-L123
Added lines #L120 - L123 were not covered by tests


126-148: Add unit tests and improve error handling.

The function has good error handling but lacks test coverage. Consider the following improvements:

  1. Add unit tests to verify fee rate estimation for both regnet and non-regnet modes.
  2. Consider using a custom error type for better error handling.

Here's a suggested improvement for error handling:

+type FeeRateError struct {
+    Reason string
+    FeeRate *float64
+}
+
+func (e *FeeRateError) Error() string {
+    return fmt.Sprintf("fee rate error: %s", e.Reason)
+}

 func (c *Client) GetEstimatedFeeRate(ctx context.Context, confTarget int64, regnet bool) (int64, error) {
     if regnet {
         return FeeRateRegnet, nil
     }

     feeResult, err := c.EstimateSmartFee(ctx, confTarget, &types.EstimateModeEconomical)
     if err != nil {
-        return 0, errors.Wrap(err, "unable to estimate smart fee")
+        return 0, &FeeRateError{Reason: "unable to estimate smart fee", FeeRate: nil}
     }
     if feeResult.Errors != nil {
-        return 0, fmt.Errorf("fee result contains errors: %s", feeResult.Errors)
+        return 0, &FeeRateError{Reason: fmt.Sprintf("fee result contains errors: %s", feeResult.Errors), FeeRate: nil}
     }
     if feeResult.FeeRate == nil {
-        return 0, fmt.Errorf("nil fee rate")
+        return 0, &FeeRateError{Reason: "nil fee rate", FeeRate: nil}
     }
     if *feeResult.FeeRate <= 0 || *feeResult.FeeRate >= maxBTCSupply {
-        return 0, fmt.Errorf("invalid fee rate: %f", *feeResult.FeeRate)
+        return 0, &FeeRateError{Reason: fmt.Sprintf("invalid fee rate: %f", *feeResult.FeeRate), FeeRate: feeResult.FeeRate}
     }

     return FeeRateToSatPerByte(*feeResult.FeeRate).Int64(), nil
 }
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 127-131: zetaclient/chains/bitcoin/client/helpers.go#L127-L131
Added lines #L127 - L131 were not covered by tests


[warning] 133-145: zetaclient/chains/bitcoin/client/helpers.go#L133-L145
Added lines #L133 - L145 were not covered by tests


[warning] 147-147: zetaclient/chains/bitcoin/client/helpers.go#L147
Added line #L147 was not covered by tests

testutil/sample/crypto.go (2)

95-104: LGTM!

The function follows best practices for generating test Bitcoin addresses and properly handles error cases.


106-111: LGTM!

The function efficiently reuses BtcAddressP2WPKH and properly generates payment scripts for testing purposes.

zetaclient/chains/bitcoin/observer/event_test.go (1)

35-35: LGTM! Consistent address string conversion.

The changes correctly handle Bitcoin address conversion to string representation, maintaining consistency across test cases.

Also applies to: 252-252, 403-403

zetaclient/chains/bitcoin/client/client_test.go (1)

140-140: LGTM! Improved assertion accuracy.

The test now correctly validates the total amount by including the depositor fee in the assertion.

zetaclient/chains/bitcoin/observer/outbound_test.go (1)

266-269: LGTM! Improved result handling with structured types.

The changes enhance code clarity by using a structured result type instead of multiple return values. This makes the code more maintainable and type-safe.

Also applies to: 274-278, 284-287, 293-296, 302-306, 312-316, 322-327, 332-336, 341-344, 363-368, 377-382, 391-401, 410-420, 435-444, 459-470

zetaclient/testutils/mocks/bitcoin_client.go (1)

360-386: LGTM! Well-structured mock implementation.

The mock implementation follows best practices with:

  • Proper panic handling for unspecified return values
  • Type assertion handling for different return scenarios
  • Consistent error propagation
x/crosschain/types/cctx_test.go (1)

143-143: LGTM! Consistent address string handling in tests.

The explicit .String() call aligns with the codebase's approach to Bitcoin address handling, ensuring consistent string representation in tests.

changelog.md (1)

10-10: LGTM! Clear and well-formatted changelog entry.

The entry follows the changelog format and clearly describes the Bitcoin RBF adoption refactoring changes.

zetaclient/chains/evm/signer/signer.go (1)

522-523: Ensure Consistent Types for HandleBroadcastError Parameters

The HandleBroadcastError function now receives cctx.GetCurrentOutboundParam().TssNonce and toChain.ID() directly without converting them to strings. Verify that HandleBroadcastError accepts these parameters as integer types (uint64 or int64) to prevent type mismatches.

zetaclient/testutils/testdata_naming.go (1)

67-70: LGTM! Clean and consistent implementation.

The function follows the established naming pattern and maintains consistency with other file naming functions in the module.

zetaclient/chains/bitcoin/observer/inbound_test.go (2)

170-170: LGTM! Consistent address string representation.

Using String() method on the Bitcoin address ensures consistent string representation across the codebase.


158-158: Verify the purpose of the empty string parameter.

The test suite initialization has been modified to include an empty string parameter. Please document the purpose of this parameter in the test setup.

zetaclient/chains/bitcoin/observer/observer_test.go Outdated Show resolved Hide resolved
zetaclient/chains/bitcoin/observer/gas_price.go Outdated Show resolved Hide resolved
zetaclient/chains/bitcoin/observer/db.go Show resolved Hide resolved
zetaclient/chains/bitcoin/signer/signer.go Show resolved Hide resolved
zetaclient/chains/bitcoin/signer/sign.go Show resolved Hide resolved
changelog.md Outdated Show resolved Hide resolved
zetaclient/chains/bitcoin/client/helpers.go Outdated Show resolved Hide resolved
zetaclient/chains/bitcoin/observer/gas_price.go Outdated Show resolved Hide resolved
zetaclient/chains/bitcoin/observer/gas_price.go Outdated Show resolved Hide resolved
@ws4charlie ws4charlie requested a review from lumtis January 21, 2025 17:00
testutil/sample/crypto.go Outdated Show resolved Hide resolved
testutil/sample/crypto.go Outdated Show resolved Hide resolved
zetaclient/chains/bitcoin/client/helpers.go Show resolved Hide resolved
zetaclient/chains/bitcoin/client/helpers.go Outdated Show resolved Hide resolved
zetaclient/chains/bitcoin/observer/gas_price.go Outdated Show resolved Hide resolved
…e fee rate according to Bitcoin network type
@ws4charlie ws4charlie requested a review from lumtis January 22, 2025 22:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
chain:bitcoin Bitcoin chain related nosec refactor zetaclient Issues related to ZetaClient
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants