-
Notifications
You must be signed in to change notification settings - Fork 157
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Begin abstraction of wallet syncing out of the wallet package.
This change begins the removal of the dcrd JSON-RPC client dependency from the wallet package and type. All notification processing to keep the wallet up to date has been moved to the chain package. This change is being performed to make switching to other network syncing backends easier in the future. Most importantly, it is required for any kind of support for both RPC and SPV network backends. To avoid some churn, the wallet must still be associated with an object that provides basic network operations such as loading data filters, fetching headers, and transaction publishing. This object is now an interface type rather than the concrete RPC client type. At the moment, this interface is currently too narrow to allow an SPV backend as a drop in replacement, but the goal is to remove methods from it until this becomes possible. There are still some features in the wallet package which do require the RPC client. These features either take the RPC client as a method parameter or assert that the network backend is the RPC client. This change also uses this API break as an opportunity to begin passing around context.Context for request-scoped cancellation and timeouts. The methods of the network backend interface all take a context, and while it is not used by the backend, they will be used for any future implementations.
- Loading branch information
Showing
21 changed files
with
1,102 additions
and
936 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
// Copyright (c) 2017 The Decred developers | ||
// Use of this source code is governed by an ISC | ||
// license that can be found in the LICENSE file. | ||
|
||
package chain | ||
|
||
import ( | ||
"context" | ||
"encoding/hex" | ||
|
||
"github.com/decred/dcrd/chaincfg/chainhash" | ||
"github.com/decred/dcrd/dcrutil" | ||
rpcclient "github.com/decred/dcrd/rpcclient" | ||
"github.com/decred/dcrd/wire" | ||
"github.com/decred/dcrwallet/apperrors" | ||
"github.com/decred/dcrwallet/wallet" | ||
"github.com/jrick/bitset" | ||
) | ||
|
||
type rpcBackend struct { | ||
rpcClient *rpcclient.Client | ||
} | ||
|
||
var _ wallet.NetworkBackend = (*rpcBackend)(nil) | ||
|
||
// BackendFromRPCClient creates a wallet network backend from an RPC client. | ||
func BackendFromRPCClient(rpcClient *rpcclient.Client) wallet.NetworkBackend { | ||
return &rpcBackend{rpcClient} | ||
} | ||
|
||
// RPCClientFromBackend returns the RPC client used to create a wallet network | ||
// backend. This errors if the backend was not created using | ||
// BackendFromRPCClient. | ||
func RPCClientFromBackend(n wallet.NetworkBackend) (*rpcclient.Client, error) { | ||
b, ok := n.(*rpcBackend) | ||
if !ok { | ||
return nil, apperrors.New(apperrors.ErrUnsupported, | ||
"this operation requires the network backend to be the consensus RPC server") | ||
} | ||
return b.rpcClient, nil | ||
} | ||
|
||
func (b *rpcBackend) GetHeaders(ctx context.Context, blockLocators []chainhash.Hash, hashStop *chainhash.Hash) ([][]byte, error) { | ||
r, err := b.rpcClient.GetHeaders(blockLocators, hashStop) | ||
if err != nil { | ||
return nil, err | ||
} | ||
headers := make([][]byte, 0, len(r.Headers)) | ||
for _, hexHeader := range r.Headers { | ||
header, err := hex.DecodeString(hexHeader) | ||
if err != nil { | ||
return nil, err | ||
} | ||
headers = append(headers, header) | ||
} | ||
return headers, nil | ||
} | ||
|
||
func (b *rpcBackend) LoadTxFilter(ctx context.Context, reload bool, addrs []dcrutil.Address, outpoints []wire.OutPoint) error { | ||
return b.rpcClient.LoadTxFilter(reload, addrs, outpoints) | ||
} | ||
|
||
func (b *rpcBackend) PublishTransaction(ctx context.Context, tx *wire.MsgTx) error { | ||
// High fees are hardcoded and allowed here since transactions created by | ||
// the wallet perform their own high fee check if high fees are disabled. | ||
// This matches the lack of any high fee checking when publishing | ||
// transactions over the wire protocol. | ||
_, err := b.rpcClient.SendRawTransaction(tx, true) | ||
return err | ||
} | ||
|
||
func (b *rpcBackend) AddressesUsed(ctx context.Context, addrs []dcrutil.Address) (bitset.Bytes, error) { | ||
hexBitSet, err := b.rpcClient.ExistsAddresses(addrs) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return hex.DecodeString(hexBitSet) | ||
} | ||
|
||
func (b *rpcBackend) Rescan(ctx context.Context, blocks []chainhash.Hash) ([]*wallet.RescannedBlock, error) { | ||
r, err := b.rpcClient.Rescan(blocks) | ||
if err != nil { | ||
return nil, err | ||
} | ||
discoveredData := make([]*wallet.RescannedBlock, 0, len(r.DiscoveredData)) | ||
for _, d := range r.DiscoveredData { | ||
blockHash, err := chainhash.NewHashFromStr(d.Hash) | ||
if err != nil { | ||
return nil, err | ||
} | ||
txs := make([][]byte, 0, len(d.Transactions)) | ||
for _, txHex := range d.Transactions { | ||
tx, err := hex.DecodeString(txHex) | ||
if err != nil { | ||
return nil, err | ||
} | ||
txs = append(txs, tx) | ||
} | ||
rescannedBlock := &wallet.RescannedBlock{ | ||
BlockHash: *blockHash, | ||
Transactions: txs, | ||
} | ||
discoveredData = append(discoveredData, rescannedBlock) | ||
} | ||
return discoveredData, nil | ||
} | ||
|
||
func (b *rpcBackend) StakeDifficulty(ctx context.Context) (dcrutil.Amount, error) { | ||
r, err := b.rpcClient.GetStakeDifficulty() | ||
if err != nil { | ||
return 0, err | ||
} | ||
return dcrutil.NewAmount(r.NextStakeDifficulty) | ||
} | ||
|
||
func (b *rpcBackend) GetBlockHash(ctx context.Context, height int32) (*chainhash.Hash, error) { | ||
return b.rpcClient.GetBlockHash(int64(height)) | ||
} |
Oops, something went wrong.