rpc: Fix block connected handler.

Fix a bug where it appeared as though a notification handler was being
attached to the dcrd RPC client, but actually no notifications were
received until the client was disconnected a new one was created.

Now, rather than delaying attaching the notification handler, it is
attached immediately upon client creation and vspd does not start
handling the received notifications until it is ready.
This commit is contained in:
jholdstock 2023-08-23 16:33:53 +01:00 committed by Jamie Holdstock
parent bac0dcef71
commit 49b9db1a64
2 changed files with 20 additions and 19 deletions

View File

@ -42,6 +42,8 @@ type vspd struct {
db *database.VspDatabase db *database.VspDatabase
dcrd rpc.DcrdConnect dcrd rpc.DcrdConnect
wallets rpc.WalletConnect wallets rpc.WalletConnect
blockNotifChan chan *wire.BlockHeader
} }
// newVspd creates the essential resources required by vspd - a database, logger // newVspd creates the essential resources required by vspd - a database, logger
@ -56,9 +58,12 @@ func newVspd(cfg *config) (*vspd, error) {
log := cfg.logger("VSP") log := cfg.logger("VSP")
rpcLog := cfg.logger("RPC") rpcLog := cfg.logger("RPC")
// Create a channel to receive blockConnected notifications from dcrd.
blockNotifChan := make(chan *wire.BlockHeader)
// Create RPC client for local dcrd instance (used for broadcasting and // Create RPC client for local dcrd instance (used for broadcasting and
// checking the status of fee transactions). // checking the status of fee transactions).
dcrd := rpc.SetupDcrd(cfg.DcrdUser, cfg.DcrdPass, cfg.DcrdHost, cfg.dcrdCert, cfg.netParams.Params, rpcLog) dcrd := rpc.SetupDcrd(cfg.DcrdUser, cfg.DcrdPass, cfg.DcrdHost, cfg.dcrdCert, cfg.netParams.Params, rpcLog, blockNotifChan)
// Create RPC client for remote dcrwallet instances (used for voting). // Create RPC client for remote dcrwallet instances (used for voting).
wallets := rpc.SetupWallet(cfg.walletUsers, cfg.walletPasswords, cfg.walletHosts, cfg.walletCerts, cfg.netParams.Params, rpcLog) wallets := rpc.SetupWallet(cfg.walletUsers, cfg.walletPasswords, cfg.walletHosts, cfg.walletCerts, cfg.netParams.Params, rpcLog)
@ -69,6 +74,8 @@ func newVspd(cfg *config) (*vspd, error) {
db: db, db: db,
dcrd: dcrd, dcrd: dcrd,
wallets: wallets, wallets: wallets,
blockNotifChan: blockNotifChan,
} }
return v, nil return v, nil
@ -162,8 +169,7 @@ func (v *vspd) run() int {
return 1 return 1
} }
// Create a channel to receive blockConnected notifications from dcrd. // Start handling blockConnected notifications from dcrd.
notifChan := make(chan *wire.BlockHeader)
shutdownWg.Add(1) shutdownWg.Add(1)
go func() { go func() {
for { for {
@ -171,16 +177,13 @@ func (v *vspd) run() int {
case <-shutdownCtx.Done(): case <-shutdownCtx.Done():
shutdownWg.Done() shutdownWg.Done()
return return
case header := <-notifChan: case header := <-v.blockNotifChan:
v.log.Debugf("Block notification %d (%s)", header.Height, header.BlockHash().String()) v.log.Debugf("Block notification %d (%s)", header.Height, header.BlockHash().String())
v.blockConnected() v.blockConnected()
} }
} }
}() }()
// Attach notification listener to dcrd client.
v.dcrd.BlockConnectedHandler(notifChan)
// Loop forever attempting ensuring a dcrd connection is available, so // Loop forever attempting ensuring a dcrd connection is available, so
// notifications are received. // notifications are received.
shutdownWg.Add(1) shutdownWg.Add(1)

View File

@ -46,21 +46,19 @@ type DcrdConnect struct {
log slog.Logger log slog.Logger
} }
func SetupDcrd(user, pass, addr string, cert []byte, params *chaincfg.Params, log slog.Logger) DcrdConnect { func SetupDcrd(user, pass, addr string, cert []byte, params *chaincfg.Params, log slog.Logger,
return DcrdConnect{ blockConnectedChan chan *wire.BlockHeader) DcrdConnect {
client: setup(user, pass, addr, cert, log), client := setup(user, pass, addr, cert, log)
params: params,
client.notifier = &blockConnectedHandler{
blockConnected: blockConnectedChan,
log: log, log: log,
} }
}
// BlockConnectedHandler attaches a blockconnected notification handler to the return DcrdConnect{
// dcrd client. Every time a notification is received, the header of the client: client,
// connected block is sent to the provided channel. params: params,
func (d *DcrdConnect) BlockConnectedHandler(blockConnected chan *wire.BlockHeader) { log: log,
d.client.notifier = &blockConnectedHandler{
blockConnected: blockConnected,
log: d.log,
} }
} }