From bf21c6c7622da280fcf7707aab46bf5e9ee3917e Mon Sep 17 00:00:00 2001 From: anvztor <15998375+anvztor@users.noreply.github.com> Date: Wed, 14 Jan 2026 14:03:58 +0800 Subject: [PATCH] fix(btcd): adapt to getblock --- go.mod | 6 ++-- go.sum | 11 +++--- internal/wallet/withdraw_broadcast.go | 51 ++++++++++++++++++--------- 3 files changed, 43 insertions(+), 25 deletions(-) diff --git a/go.mod b/go.mod index 26a7642..dfb85fd 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.8 toolchain go1.24.3 require ( - github.com/btcsuite/btcd v0.24.2 + github.com/btcsuite/btcd v0.25.0 github.com/btcsuite/btcd/btcutil v1.1.6 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 github.com/cometbft/cometbft v0.38.17 @@ -141,7 +141,7 @@ require ( google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a // indirect nhooyr.io/websocket v1.8.6 // indirect - pgregory.net/rapid v1.1.0 // indirect + pgregory.net/rapid v1.2.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) @@ -152,7 +152,7 @@ require ( github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.17.0 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.3.4 + github.com/btcsuite/btcd/btcec/v2 v2.3.6 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect diff --git a/go.sum b/go.sum index 0f44b8d..5208651 100644 --- a/go.sum +++ b/go.sum @@ -85,12 +85,13 @@ github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBT github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= -github.com/btcsuite/btcd v0.24.2 h1:aLmxPguqxza+4ag8R1I2nnJjSu2iFn/kqtHTIImswcY= github.com/btcsuite/btcd v0.24.2/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= +github.com/btcsuite/btcd v0.25.0 h1:JPbjwvHGpSywBRuorFFqTjaVP4y6Qw69XJ1nQ6MyWJM= +github.com/btcsuite/btcd v0.25.0/go.mod h1:qbPE+pEiR9643E1s1xu57awsRhlCIm1ZIi6FfeRA4KE= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= -github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= -github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/btcec/v2 v2.3.6 h1:IzlsEr9olcSRKB/n7c4351F3xHKxS2lma+1UFGCYd4E= +github.com/btcsuite/btcd/btcec/v2 v2.3.6/go.mod h1:m22FrOAiuxl/tht9wIqAoGHcbnCCaPWyauO8y2LGGtQ= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= @@ -1443,8 +1444,8 @@ lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= -pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= -pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= +pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= +pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/internal/wallet/withdraw_broadcast.go b/internal/wallet/withdraw_broadcast.go index aeacfa4..171e228 100644 --- a/internal/wallet/withdraw_broadcast.go +++ b/internal/wallet/withdraw_broadcast.go @@ -92,34 +92,51 @@ func (c *BtcClient) SendRawTransaction(tx *wire.MsgTx, utxos []*db.Utxo, orderTy return txid, false, nil } -// sendRawTransactionDirect sends a raw transaction using SendCmd directly, -// bypassing BackendVersion() detection which fails with some RPC providers (e.g., GetBlock) -func sendRawTransactionDirect(client *rpcclient.Client, tx *wire.MsgTx) error { - // Serialize the transaction to hex - var buf bytes.Buffer - if err := tx.Serialize(&buf); err != nil { - return fmt.Errorf("failed to serialize tx: %v", err) - } - txHex := hex.EncodeToString(buf.Bytes()) - - // Create sendrawtransaction command (bitcoind format with maxfeerate=0 to disable fee check) - cmd := btcjson.NewSendRawTransactionCmd(txHex, nil) +// sendRawTransactionBitcoind sends using Bitcoin Core format: sendrawtransaction "hex" [maxfeerate(number)] +func sendRawTransactionBitcoind(client *rpcclient.Client, txHex string) error { + cmd := btcjson.NewBitcoindSendRawTransactionCmd(txHex, 0) + respChan := client.SendCmd(cmd) + _, err := rpcclient.ReceiveFuture(respChan) + return err +} - // Send command directly without version detection +// sendRawTransactionBtcd sends using btcd format: sendrawtransaction "hex" [allowhighfees(bool)] +func sendRawTransactionBtcd(client *rpcclient.Client, txHex string) error { + allowHighFees := false + cmd := btcjson.NewSendRawTransactionCmd(txHex, &allowHighFees) respChan := client.SendCmd(cmd) _, err := rpcclient.ReceiveFuture(respChan) return err } -// sendRawTransactionWithFallback tries standard method first, falls back to direct method +// sendRawTransactionWithFallback tries multiple methods to send raw transaction: +// 1. Standard method (uses BackendVersion detection) +// 2. Bitcoin Core format (maxfeerate=0) +// 3. btcd format (allowhighfees=false) func sendRawTransactionWithFallback(client *rpcclient.Client, tx *wire.MsgTx) error { + // Try standard method first _, err := client.SendRawTransaction(tx, false) if err == nil { return nil } - // Fallback to direct method for RPC providers that don't support getinfo (e.g., GetBlock) - log.Warnf("SendRawTransaction failed with standard method: %v, trying direct method", err) - return sendRawTransactionDirect(client, tx) + log.Warnf("SendRawTransaction standard method failed: %v, trying bitcoind format", err) + + // Serialize tx for direct methods + var buf bytes.Buffer + if serErr := tx.Serialize(&buf); serErr != nil { + return fmt.Errorf("failed to serialize tx: %v", serErr) + } + txHex := hex.EncodeToString(buf.Bytes()) + + // Try Bitcoin Core format (maxfeerate=0) + err = sendRawTransactionBitcoind(client, txHex) + if err == nil { + return nil + } + log.Warnf("SendRawTransaction bitcoind format failed: %v, trying btcd format", err) + + // Try btcd format (allowhighfees=false) + return sendRawTransactionBtcd(client, txHex) } func (c *BtcClient) CheckPending(txid string, externalTxId string, updatedAt time.Time) (revert bool, confirmations uint64, blockHeight uint64, err error) {