Skip to content

Commit c85165c

Browse files
committed
Consistent preconditions for SPV/RPC sync.
In order to start a wallet sync over either RPC or SPV, the wallet must already be loaded and must not already have an associated syncer. RpcSync was missing the check for a loaded wallet (which could lead to a panic). SpvSync was missing the check for an already existing syncer.
1 parent f27b4b0 commit c85165c

1 file changed

Lines changed: 23 additions & 11 deletions

File tree

internal/rpc/rpcserver/server.go

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Copyright (c) 2015-2016 The btcsuite developers
2-
// Copyright (c) 2016-2025 The Decred developers
2+
// Copyright (c) 2016-2026 The Decred developers
33
// Use of this source code is governed by an ISC
44
// license that can be found in the LICENSE file.
55

@@ -2832,13 +2832,17 @@ func isLoopback(addr string) bool {
28322832
func (s *loaderServer) RpcSync(req *pb.RpcSyncRequest, svr pb.WalletLoaderService_RpcSyncServer) error {
28332833
defer zero(req.Password)
28342834

2835-
// Error if the wallet is already syncing with the network.
28362835
wallet, walletLoaded := s.loader.LoadedWallet()
2837-
if walletLoaded {
2838-
_, err := wallet.NetworkBackend()
2839-
if err == nil {
2840-
return status.Errorf(codes.FailedPrecondition, "wallet is loaded and already synchronizing")
2841-
}
2836+
2837+
// Wallet must be loaded before sync can start.
2838+
if !walletLoaded {
2839+
return status.Errorf(codes.FailedPrecondition, "Wallet has not been loaded")
2840+
}
2841+
2842+
// Error if the wallet is already syncing with the network.
2843+
_, err := wallet.NetworkBackend()
2844+
if err == nil {
2845+
return status.Errorf(codes.FailedPrecondition, "wallet is loaded and already synchronizing")
28422846
}
28432847

28442848
if req.DiscoverAccounts && len(req.PrivatePassphrase) == 0 {
@@ -2966,7 +2970,7 @@ func (s *loaderServer) RpcSync(req *pb.RpcSyncRequest, svr pb.WalletLoaderServic
29662970
syncer.SetCallbacks(cbs)
29672971

29682972
// Synchronize until error or RPC cancellation.
2969-
err := syncer.Run(svr.Context())
2973+
err = syncer.Run(svr.Context())
29702974
if err != nil {
29712975
if svr.Context().Err() != nil {
29722976
return status.Errorf(codes.Canceled, "Wallet synchronization canceled: %v", err)
@@ -2978,11 +2982,19 @@ func (s *loaderServer) RpcSync(req *pb.RpcSyncRequest, svr pb.WalletLoaderServic
29782982
}
29792983

29802984
func (s *loaderServer) SpvSync(req *pb.SpvSyncRequest, svr pb.WalletLoaderService_SpvSyncServer) error {
2981-
wallet, ok := s.loader.LoadedWallet()
2982-
if !ok {
2985+
wallet, walletLoaded := s.loader.LoadedWallet()
2986+
2987+
// Wallet must be loaded before sync can start.
2988+
if !walletLoaded {
29832989
return status.Errorf(codes.FailedPrecondition, "Wallet has not been loaded")
29842990
}
29852991

2992+
// Error if the wallet is already syncing with the network.
2993+
_, err := wallet.NetworkBackend()
2994+
if err == nil {
2995+
return status.Errorf(codes.FailedPrecondition, "wallet is loaded and already synchronizing")
2996+
}
2997+
29862998
if req.DiscoverAccounts && len(req.PrivatePassphrase) == 0 {
29872999
return status.Errorf(codes.InvalidArgument, "private passphrase is required for discovering accounts")
29883000
}
@@ -3133,7 +3145,7 @@ func (s *loaderServer) SpvSync(req *pb.SpvSyncRequest, svr pb.WalletLoaderServic
31333145
syncer.SetPersistentPeers(spvConnects)
31343146
}
31353147

3136-
err := syncer.Run(svr.Context())
3148+
err = syncer.Run(svr.Context())
31373149
if err != nil {
31383150
if errors.Is(err, context.Canceled) {
31393151
return status.Errorf(codes.Canceled, "SPV synchronization canceled: %v", err)

0 commit comments

Comments
 (0)