-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Open
Labels
Description
Background
when .GetBlockTemplate is called right after a block rolls in, and the websocket interface is in use, btcd fails and GetBlockTemplate hangs. trying to then stop the client with .Shutdown() also hangs.
Your environment
- version of
btcd: 0.25.0 - which operating system: EndeavourOS
- any other relevant environment details
imported deps:
github.com/btcsuite/btcd v0.25.0
github.com/btcsuite/btcd/btcutil v1.1.7-0.20251106010755-9ff0780da683
github.com/btcsuite/btcd/btcec/v2 v2.3.6 // indirect
github.com/btcsuite/btclog v1.0.0 // indirect
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect
Steps to reproduce
- Set up
rpcclientusing the websocket interface - trigger a gbt after blocks come in
- wait a couple hours for it to freeze
- try to SIGINT
- watch it not stop
I sometimes (sometimes!!!! >:C) get an error from btcd too when it occurs:
2025-11-14 04:01:43.355 [DBG] RPCS: Received command <getblocktemplate> from [::1]:44984 # erroring gbt
2025-11-14 04:01:43.355 [DBG] MINR: Considering 2987 transactions for inclusion to new block
2025-11-14 04:01:43.853 [ERR] RPCS: Failed to create new block template: previous block must be the current chain tip 00000000000000000000a6c2839f8c2bea4f7b31c63f4bce11303007f85b3653, instead got 000000000000000000002a22ca81d279bd95d772b7c8fa3e5ed7a0ba303b0694
2025-11-14 04:01:44.356 [DBG] RPCS: Received command <getblocktemplate> from [::1]:44984 # retry loop, iter 1
2025-11-14 04:01:44.356 [DBG] MINR: Considering 573 transactions for inclusion to new block
2025-11-14 04:01:44.657 [DBG] MINR: Created new block template (501 transactions, 361584 in fees, 2031 signature operations cost, 3875333 weight, target difficulty 00000000000000000001d9360000000000000000000000000000000000000000)
2025-11-14 04:01:44.657 [DBG] RPCS: Generated block template (timestamp 2025-11-14 04:01:44 -0500 EST, target 00000000000000000001d9360000000000000000000000000000000000000000, merkle root 16fff92883e2c19c15062f2f727352734ca537ed37030fd7127b3db7688e5729)
# this is where gbt hangs in the code snippet
code sample:
package main
import (
"log"
"os"
"os/signal"
"syscall"
"time"
"github.com/btcsuite/btcd/btcjson"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/rpcclient"
"github.com/btcsuite/btcd/wire"
)
func main() {
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
triggerGBT := make(chan struct{})
backendConnConf := &rpcclient.ConnConfig{
Host: "localhost:8334",
DisableTLS: true,
HTTPPostMode: false,
Endpoint: "ws",
User: "btcd",
Pass: "btcd",
}
backend, err := rpcclient.New(backendConnConf, &rpcclient.NotificationHandlers{
OnFilteredBlockConnected: func(height int32, header *wire.BlockHeader, _ []*btcutil.Tx) {
log.Printf("new block %d\n%s\n", height, header.BlockHash())
/// GBT fail trigger
triggerGBT <- struct{}{}
},
OnFilteredBlockDisconnected: func(_ int32, _ *wire.BlockHeader) {},
})
if err != nil {
log.Panicf("failed to connect to backend: %s", err)
}
if err := backend.NotifyBlocks(); err != nil {
log.Panicf("failed to subscribe to block notifications: %s", err)
}
go func() {
log.Print("waiting for blocks...")
for {
template, err := backend.GetBlockTemplate(&btcjson.TemplateRequest{
Rules: []string{"segwit"}, /// required by gbt
Capabilities: []string{"proposal", "coinbasevalue", "longpoll"},
Mode: "template",
})
if err != nil {
log.Printf("error fetching template: %s\n", err)
time.Sleep(time.Millisecond * 500)
continue
}
log.Printf("gbt success, %d txns\n", len(template.Transactions))
<-triggerGBT
}
}()
<-sigs
log.Println("shutting down")
backend.Shutdown() /// Doesn't progress past here
log.Println("waiting for shutdown")
backend.WaitForShutdown()
}
running this consistently triggers the error after a couple of hours.
Expected behaviour
i expected the client to not freeze.
Actual behaviour
the client freezes and needs to be SIGKILLed.
Reactions are currently unavailable