Skip to content

Commit

Permalink
Remove gRPC methods that are obsoleted by RpcSync.
Browse files Browse the repository at this point in the history
The removed methods of the WalletService are:

* StartConsensusRpc
* DiscoverAddresses
* SubscribeToBlockNotifications
* FetchHeaders
* FetchMissingCFilters

The API major version is bumped to 7 for this breaking change.
  • Loading branch information
jrick committed Jul 3, 2019
1 parent b65ddc1 commit 0988aa6
Show file tree
Hide file tree
Showing 4 changed files with 524 additions and 1,028 deletions.
5 changes: 0 additions & 5 deletions rpc/api.proto
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,6 @@ service WalletLoaderService {
rpc CreateWatchingOnlyWallet (CreateWatchingOnlyWalletRequest) returns (CreateWatchingOnlyWalletResponse);
rpc OpenWallet (OpenWalletRequest) returns (OpenWalletResponse);
rpc CloseWallet (CloseWalletRequest) returns (CloseWalletResponse);
rpc StartConsensusRpc (StartConsensusRpcRequest) returns (StartConsensusRpcResponse);
rpc DiscoverAddresses (DiscoverAddressesRequest) returns (DiscoverAddressesResponse);
rpc SubscribeToBlockNotifications (SubscribeToBlockNotificationsRequest) returns (SubscribeToBlockNotificationsResponse);
rpc FetchHeaders(FetchHeadersRequest) returns (FetchHeadersResponse);
rpc FetchMissingCFilters(FetchMissingCFiltersRequest) returns (FetchMissingCFiltersResponse);
rpc SpvSync(SpvSyncRequest) returns (stream SpvSyncResponse);
rpc RpcSync(RpcSyncRequest) returns (stream RpcSyncResponse);
rpc RescanPoint(RescanPointRequest) returns (RescanPointResponse);
Expand Down
149 changes: 1 addition & 148 deletions rpc/documentation/api.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# RPC API Specification

Version: 5.8.x
Version: 7.0.x

**Note:** This document assumes the reader is familiar with gRPC concepts.
Refer to the [gRPC Concepts documentation](https://www.grpc.io/docs/guides/concepts.html)
Expand Down Expand Up @@ -93,11 +93,6 @@ no dependencies and is always running.
- [`CreateWatchingOnlyWallet`](#createwatchingonlywallet)
- [`OpenWallet`](#openwallet)
- [`CloseWallet`](#closewallet)
- [`StartConsensusRpc`](#startconsensusrpc)
- [`DiscoverAddresses`](#discoveraddresses)
- [`SubscribeToBlockNotifications`](#subscribetoblocknotifications)
- [`FetchHeaders`](#fetchheaders)
- [`FetchMissingCFilters`](#fetchmissingcfilters)
- [`RescanPoint`](#rescanpoint)
- [`SpvSync`](#spvsync)
- [`RpcSync`](#rpcsync)
Expand Down Expand Up @@ -238,148 +233,6 @@ unusable.

___

#### `StartConsensusRpc`

The `StartConsensusRpc` method is used to provide clients the ability to
dynamically start the dcrd RPC client. This RPC client is used for wallet
syncing and publishing transactions to the Decred network.

Since API version 3.0.0, starting the consensus server no longer automatically
synchronizes the wallet to the consensus server if it was previously loaded.

**Request:** `StartConsensusRpcRequest`

- `string network_address`: The host/IP and optional port of the RPC server to
connect to. IP addresses may be IPv4 or IPv6. If the port is missing, a
default port is chosen corresponding to the default dcrd RPC port of the
active Decred network.

- `string username`: The RPC username required to authenticate to the RPC
server.

- `bytes password`: The RPC password required to authenticate to the RPC server.

- `bytes certificate`: The consensus RPC server's TLS certificate. If this
field has zero length and the network address describes a loopback connection
(`localhost`, `127.0.0.1`, or `::1`) TLS will be disabled.

**Response:** `StartConsensusRpcResponse`

**Expected errors:**

- `FailedPrecondition`: A consensus RPC client is already active.

- `InvalidArgument`: The network address is ill-formatted or does not contain a
valid IP address.

- `NotFound`: The consensus RPC server is unreachable. This condition may not
return `Unavailable` as that refers to `WalletLoaderService` itself being
unavailable.

- `InvalidArgument`: The username, password, or certificate are invalid. This
condition may not be return `Unauthenticated` as that refers to the client not
having the credentials to call this method.

___

#### `DiscoverAddresses`

The `DiscoverAddresses` method performs BIP0044 address discovery for the wallet
with optional account discovery using the loaded consensus RPC server (required
for querying for known used addresses). Account discovery requires the wallet
to be unlocked in order to derive account hardened extended pubkeys, and thus
the private passphrase must be passed as a parameter when performing this
action. Account discovery is typically only required when reseeding a wallet.
Address discovery begins at the provided starting block hash. If none
is provided, then the current network's genesis hash will be used.

**Request:** `DiscoverAddressesRequest`

- `bool discover_accounts`: In addition to syncing addresses for already derived
accounts, also look ahead for other used accounts.

- `bytes private_passphrase`: The private passphrase to unlock the wallet when
account discovery is enabled.

- `bytes starting_block_hash`: The hash of the first block checked for address
and account usage. This must also be a valid hash of a main chain block.

**Response:** `DiscoverAddressesResponse`

**Expected Errors:**

- `FailedPrecondition`: The wallet or consensus RPC server has not been opened.

- `InvalidArgument`: A zero length passphrase passphrase was specified when
account discovery was enabled, or the passphrase was incorrect, or if an
invalid starting block hash is provided.

___

#### `SubscribeToBlockNotifications`

The `SubscribeToBlockNotifications` method associates the wallet with the
consensus RPC server, subscribes the wallet for attached block and chain switch
notifications, and causes the wallet to process these notifications in the
background.

**Request:** `SubscribeToBlockNotificationsRequest`

**Response:** `SubscribeToBlockNotificationsResponse`

**Expected Errors:**

- `FailedPrecondition`: The wallet or consensus RPC server has not been opened.

___

#### `FetchHeaders`

The `FetchHeaders` method fetches main chain block headers from the opened
consensus server client. The response includes the hash and height of the first
new block added to the main chain, if any. This is the block that a rescan
should begin at.

**Request:** `FetchHeadersRequest`

**Response:** `FetchHeadersResponse`

- `uint32 fetched_headers_count`: The number of new headers attached to the main
chain.

- `bytes first_new_block_hash`: The hash of the first new block added to the
main chain. Only non-null when `fetched_headers_count` is not zero.

- `int32 first_new_block_height`: The height of the first new block added to the
main chain. Only non-zero when `fetched_headers_count` is not zero.

- `bytes main_chain_tip_block_hash`: The hash of the main chain tip block after
the fetched headers have been applied to the previous tip.

- `int32 main_chain_tip_block_height`: The height of the main chain tip block after
the fetched headers have been applied to the previous tip.

**Expected errors:**

- `FailedPrecondition`: The wallet or consensus RPC server has not been opened.

___

#### `FetchMissingCFilters`

The `FetchMissingCFilters` method fetches any missing committed filters for
blocks in the wallet's main chain.

**Request:** `FetchMissingCFiltersRequest`

**Response:** `FetchMissingCFiltersResponse`

**Expected errors:**

- `FailedPrecondition`: The wallet or consensus RPC server has not been opened.

___

#### `RescanPoint`

The `RescanPoint` returns the block hash at which a rescan should begin
Expand Down
186 changes: 2 additions & 184 deletions rpc/rpcserver/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ import (

// Public API version constants
const (
semverString = "6.0.0"
semverMajor = 6
semverString = "7.0.0"
semverMajor = 7
semverMinor = 0
semverPatch = 0
)
Expand Down Expand Up @@ -2325,122 +2325,6 @@ func (s *loaderServer) CloseWallet(ctx context.Context, req *pb.CloseWalletReque
return &pb.CloseWalletResponse{}, nil
}

func (s *loaderServer) StartConsensusRpc(ctx context.Context, req *pb.StartConsensusRpcRequest) (
*pb.StartConsensusRpcResponse, error) {

defer zero.Bytes(req.Password)

defer s.mu.Unlock()
s.mu.Lock()

if s.rpcClient != nil {
return nil, status.Errorf(codes.FailedPrecondition, "RPC client already created")
}

networkAddress, err := cfgutil.NormalizeAddress(req.NetworkAddress,
s.activeNet.JSONRPCClientPort)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument,
"Network address is ill-formed: %v", err)
}

// Error if the wallet is already syncing with the network.
wallet, walletLoaded := s.loader.LoadedWallet()
if walletLoaded {
_, err := wallet.NetworkBackend()
if err == nil {
return nil, status.Errorf(codes.FailedPrecondition,
"wallet is loaded and already synchronizing")
}
}

rpcClient, err := chain.NewRPCClient(s.activeNet.Params, networkAddress, req.Username,
string(req.Password), req.Certificate, len(req.Certificate) == 0)
if err != nil {
return nil, translateError(err)
}

err = rpcClient.Start(ctx, false)
if err != nil {
if err == rpcclient.ErrInvalidAuth {
return nil, status.Errorf(codes.InvalidArgument,
"Invalid RPC credentials: %v", err)
}
return nil, status.Errorf(codes.NotFound,
"Connection to RPC server failed: %v", err)
}

s.rpcClient = rpcClient
s.loader.SetNetworkBackend(chain.BackendFromRPCClient(rpcClient.Client))

return &pb.StartConsensusRpcResponse{}, nil
}

func (s *loaderServer) DiscoverAddresses(ctx context.Context, req *pb.DiscoverAddressesRequest) (
*pb.DiscoverAddressesResponse, error) {

wallet, ok := s.loader.LoadedWallet()
if !ok {
return nil, status.Errorf(codes.FailedPrecondition, "Wallet has not been loaded")
}

s.mu.Lock()
chainClient := s.rpcClient
s.mu.Unlock()
if chainClient == nil {
return nil, status.Errorf(codes.FailedPrecondition, "Consensus server RPC client has not been loaded")
}

if req.DiscoverAccounts && len(req.PrivatePassphrase) == 0 {
return nil, status.Errorf(codes.InvalidArgument, "private passphrase is required for discovering accounts")
}

if req.DiscoverAccounts {
lock := make(chan time.Time, 1)
defer func() {
lock <- time.Time{}
zero.Bytes(req.PrivatePassphrase)
}()
err := wallet.Unlock(req.PrivatePassphrase, lock)
if err != nil {
return nil, translateError(err)
}
}
n := chain.BackendFromRPCClient(chainClient.Client)
startHash := wallet.ChainParams().GenesisHash
var err error
if req.StartingBlockHash != nil {
startHash, err = chainhash.NewHash(req.StartingBlockHash)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "Invalid starting block hash provided: %v", err)
}
}
err = wallet.DiscoverActiveAddresses(ctx, n, startHash, req.DiscoverAccounts)
if err != nil {
return nil, translateError(err)
}

return &pb.DiscoverAddressesResponse{}, nil
}

func (s *loaderServer) FetchMissingCFilters(ctx context.Context, req *pb.FetchMissingCFiltersRequest) (
*pb.FetchMissingCFiltersResponse, error) {

wallet, ok := s.loader.LoadedWallet()
if !ok {
return nil, status.Errorf(codes.FailedPrecondition, "Wallet has not been loaded")
}

n := chain.BackendFromRPCClient(s.rpcClient.Client)
// Fetch any missing main chain compact filters.
err := wallet.FetchMissingCFilters(ctx, n)
if err != nil {
return nil, err
}

return &pb.FetchMissingCFiltersResponse{}, nil
}

func (s *loaderServer) RpcSync(req *pb.RpcSyncRequest, svr pb.WalletLoaderService_RpcSyncServer) error {
defer zero.Bytes(req.Password)

Expand Down Expand Up @@ -2815,72 +2699,6 @@ func (s *loaderServer) RescanPoint(ctx context.Context, req *pb.RescanPointReque
return &pb.RescanPointResponse{RescanPointHash: nil}, nil
}

func (s *loaderServer) SubscribeToBlockNotifications(ctx context.Context, req *pb.SubscribeToBlockNotificationsRequest) (
*pb.SubscribeToBlockNotificationsResponse, error) {

wallet, ok := s.loader.LoadedWallet()
if !ok {
return nil, status.Errorf(codes.FailedPrecondition, "Wallet has not been loaded")
}

s.mu.Lock()
chainClient := s.rpcClient
s.mu.Unlock()
if chainClient == nil {
return nil, status.Errorf(codes.FailedPrecondition, "Consensus server RPC client has not been loaded")
}

err := chainClient.NotifyBlocks()
if err != nil {
return nil, translateError(err)
}

// TODO: instead of running the syncer in the background indefinitely,
// deprecate this RPC and introduce two new RPCs, one to subscribe to the
// notifications and one to perform the synchronization task. This would be
// a backwards-compatible way to improve error handling and provide more
// control over how long the synchronization task runs.
syncer := chain.NewRPCSyncer(wallet, chainClient)
go syncer.Run(context.Background(), false)
wallet.SetNetworkBackend(chain.BackendFromRPCClient(chainClient.Client))

return &pb.SubscribeToBlockNotificationsResponse{}, nil
}

func (s *loaderServer) FetchHeaders(ctx context.Context, req *pb.FetchHeadersRequest) (
*pb.FetchHeadersResponse, error) {

wallet, ok := s.loader.LoadedWallet()
if !ok {
return nil, status.Errorf(codes.FailedPrecondition, "Wallet has not been loaded")
}

s.mu.Lock()
chainClient := s.rpcClient
s.mu.Unlock()
if chainClient == nil {
return nil, status.Errorf(codes.FailedPrecondition, "Consensus server RPC client has not been loaded")
}
n := chain.BackendFromRPCClient(chainClient.Client)

fetchedHeaderCount, rescanFrom, rescanFromHeight,
mainChainTipBlockHash, mainChainTipBlockHeight, err := wallet.FetchHeaders(ctx, n)
if err != nil {
return nil, translateError(err)
}

res := &pb.FetchHeadersResponse{
FetchedHeadersCount: uint32(fetchedHeaderCount),
MainChainTipBlockHash: mainChainTipBlockHash[:],
MainChainTipBlockHeight: mainChainTipBlockHeight,
}
if fetchedHeaderCount > 0 {
res.FirstNewBlockHash = rescanFrom[:]
res.FirstNewBlockHeight = rescanFromHeight
}
return res, nil
}

func (s *seedServer) GenerateRandomSeed(ctx context.Context, req *pb.GenerateRandomSeedRequest) (
*pb.GenerateRandomSeedResponse, error) {

Expand Down
Loading

0 comments on commit 0988aa6

Please sign in to comment.