From 714beab7a1fe6591c0dabf6472e20b804f4f24d8 Mon Sep 17 00:00:00 2001 From: Charlie Chen <34498985+ws4charlie@users.noreply.github.com> Date: Thu, 23 May 2024 12:24:58 -0500 Subject: [PATCH] fix: incorrect bitcoin outbound height (#2243) * fix old block height bug * added changelog entry and fix code format --- changelog.md | 1 + .../chains/bitcoin/observer/live_test.go | 30 +++++++++++++++++-- .../chains/bitcoin/observer/observer.go | 20 +++++++++++++ .../chains/bitcoin/observer/outbound.go | 12 +++++++- 4 files changed, 60 insertions(+), 3 deletions(-) diff --git a/changelog.md b/changelog.md index 095b9ec6e4..d6fe7eae59 100644 --- a/changelog.md +++ b/changelog.md @@ -43,6 +43,7 @@ * [2125](https://github.com/zeta-chain/node/pull/2125) - fix develop upgrade test * [2222](https://github.com/zeta-chain/node/pull/2222) - removed `maxHeightDiff` to let observer scan from Bitcoin height where it left off * [2233](https://github.com/zeta-chain/node/pull/2233) - fix `IsSupported` flag not properly updated in zetaclient's context +* [2243](https://github.com/zeta-chain/node/pull/2243) - fix incorrect bitcoin outbound height in the CCTX outbound parameter ### CI diff --git a/zetaclient/chains/bitcoin/observer/live_test.go b/zetaclient/chains/bitcoin/observer/live_test.go index f35637d7cc..abc0545db6 100644 --- a/zetaclient/chains/bitcoin/observer/live_test.go +++ b/zetaclient/chains/bitcoin/observer/live_test.go @@ -5,6 +5,7 @@ import ( "encoding/hex" "fmt" "math/big" + "os" "strings" "testing" "time" @@ -86,10 +87,13 @@ func (suite *BitcoinObserverTestSuite) TearDownSuite() { func getRPCClient(chainID int64) (*rpcclient.Client, error) { var connCfg *rpcclient.ConnConfig + rpcMainnet := os.Getenv("BTC_RPC_MAINNET") + rpcTestnet := os.Getenv("BTC_RPC_TESTNET") + // mainnet if chainID == 8332 { connCfg = &rpcclient.ConnConfig{ - Host: "127.0.0.1:8332", // mainnet endpoint goes here + Host: rpcMainnet, // mainnet endpoint goes here User: "user", Pass: "pass", Params: "mainnet", @@ -100,7 +104,7 @@ func getRPCClient(chainID int64) (*rpcclient.Client, error) { // testnet3 if chainID == 18332 { connCfg = &rpcclient.ConnConfig{ - Host: "127.0.0.1:8332", // testnet endpoint goes here + Host: rpcTestnet, // testnet endpoint goes here User: "user", Pass: "pass", Params: "testnet3", @@ -219,12 +223,34 @@ func (suite *BitcoinObserverTestSuite) Test3() { func TestBitcoinObserverLive(t *testing.T) { // suite.Run(t, new(BitcoinClientTestSuite)) + // LiveTestGetBlockHeightByHash(t) // LiveTestBitcoinFeeRate(t) // LiveTestAvgFeeRateMainnetMempoolSpace(t) // LiveTestAvgFeeRateTestnetMempoolSpace(t) // LiveTestGetSenderByVin(t) } +// LiveTestGetBlockHeightByHash queries Bitcoin block height by hash +func LiveTestGetBlockHeightByHash(t *testing.T) { + // setup Bitcoin client + client, err := getRPCClient(8332) + require.NoError(t, err) + + // the block hashes to test + expectedHeight := int64(835053) + hash := "00000000000000000000994a5d12976ec5bda078a7b9c27981f0a4e7a6d46d23" + invalidHash := "invalidhash" + + // get block by invalid hash + _, err = GetBlockHeightByHash(client, invalidHash) + require.ErrorContains(t, err, "error decoding block hash") + + // get block height by block hash + height, err := GetBlockHeightByHash(client, hash) + require.NoError(t, err) + require.Equal(t, expectedHeight, height) +} + // LiveTestBitcoinFeeRate query Bitcoin mainnet fee rate every 5 minutes // and compares Conservative and Economical fee rates for different block targets (1 and 2) func LiveTestBitcoinFeeRate(t *testing.T) { diff --git a/zetaclient/chains/bitcoin/observer/observer.go b/zetaclient/chains/bitcoin/observer/observer.go index 9b823e1b6d..0a4a062aef 100644 --- a/zetaclient/chains/bitcoin/observer/observer.go +++ b/zetaclient/chains/bitcoin/observer/observer.go @@ -634,6 +634,26 @@ func GetTxResultByHash( return hash, txResult, nil } +// GetBlockHeightByTxHash gets the block height by block hash +func GetBlockHeightByHash( + rpcClient interfaces.BTCRPCClient, + hash string, +) (int64, error) { + // decode the block hash + var blockHash chainhash.Hash + err := chainhash.Decode(&blockHash, hash) + if err != nil { + return 0, errors.Wrapf(err, "GetBlockHeightByHash: error decoding block hash %s", hash) + } + + // get block by hash + block, err := rpcClient.GetBlockVerbose(&blockHash) + if err != nil { + return 0, errors.Wrapf(err, "GetBlockHeightByHash: error GetBlockVerbose %s", hash) + } + return block.Height, nil +} + // GetRawTxResult gets the raw tx result func GetRawTxResult( rpcClient interfaces.BTCRPCClient, diff --git a/zetaclient/chains/bitcoin/observer/outbound.go b/zetaclient/chains/bitcoin/observer/outbound.go index 74459e5b9d..a17d46883f 100644 --- a/zetaclient/chains/bitcoin/observer/outbound.go +++ b/zetaclient/chains/bitcoin/observer/outbound.go @@ -161,12 +161,22 @@ func (ob *Observer) IsOutboundProcessed(cctx *crosschaintypes.CrossChainTx, logg return true, false, nil } + // Get outbound block height + blockHeight, err := GetBlockHeightByHash(ob.rpcClient, res.BlockHash) + if err != nil { + return true, false, errors.Wrapf( + err, + "IsOutboundProcessed: error getting block height by hash %s", + res.BlockHash, + ) + } + logger.Debug().Msgf("Bitcoin outbound confirmed: txid %s, amount %s\n", res.TxID, amountInSat.String()) zetaHash, ballot, err := ob.zetacoreClient.PostVoteOutbound( sendHash, res.TxID, // #nosec G701 always positive - uint64(res.BlockIndex), + uint64(blockHeight), 0, // gas used not used with Bitcoin nil, // gas price not used with Bitcoin 0, // gas limit not used with Bitcoin