Skip to content

Commit

Permalink
Make rescan a struct, add spending tx to GetUtxo, start integration.
Browse files Browse the repository at this point in the history
  • Loading branch information
aakselrod committed May 16, 2017
1 parent 5427079 commit 8af0920
Show file tree
Hide file tree
Showing 9 changed files with 574 additions and 187 deletions.
25 changes: 25 additions & 0 deletions chain/interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package chain

import (
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
"github.com/btcsuite/btcwallet/waddrmgr"
)

// Interface allows more than one backing blockchain source, such as a
// btcd RPC chain server, or an SPV library, as long as we write a driver for
// it.
type Interface interface {
Start() error
Stop()
WaitForShutdown()
GetBestBlock() (*chainhash.Hash, int32, error)
GetBlock(*chainhash.Hash) (*wire.MsgBlock, error)
BlockStamp() (*waddrmgr.BlockStamp, error)
SendRawTransaction(*wire.MsgTx, bool) (*chainhash.Hash, error)
Rescan(*chainhash.Hash, []btcutil.Address, []*wire.OutPoint) error
NotifyReceived([]btcutil.Address) error
NotifyBlocks() error
Notifications() <-chan interface{}
}
16 changes: 16 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ import (
"runtime"
"sort"
"strings"
"time"

"github.com/btcsuite/btcutil"
"github.com/btcsuite/btcwallet/internal/cfgutil"
"github.com/btcsuite/btcwallet/internal/legacy/keystore"
"github.com/btcsuite/btcwallet/netparams"
"github.com/btcsuite/btcwallet/spvsvc/spvchain"
"github.com/btcsuite/btcwallet/wallet"
flags "github.com/jessevdk/go-flags"
)
Expand Down Expand Up @@ -70,6 +72,14 @@ type config struct {
ProxyUser string `long:"proxyuser" description:"Username for proxy server"`
ProxyPass string `long:"proxypass" default-mask:"-" description:"Password for proxy server"`

// SPV client options
UseSPV bool `long:"usespv" description:"Enables the experimental use of SPV rather than RPC for chain synchronization"`
AddPeers []string `short:"a" long:"addpeer" description:"Add a peer to connect with at startup"`
ConnectPeers []string `long:"connect" description:"Connect only to the specified peers at startup"`
MaxPeers int `long:"maxpeers" description:"Max number of inbound and outbound peers"`
BanDuration time.Duration `long:"banduration" description:"How long to ban misbehaving peers. Valid time units are {s, m, h}. Minimum 1 second"`
BanThreshold uint32 `long:"banthreshold" description:"Maximum allowed ban score before disconnecting and banning misbehaving peers."`

// RPC server options
//
// The legacy server is still enabled by default (and eventually will be
Expand Down Expand Up @@ -257,6 +267,12 @@ func loadConfig() (*config, []string, error) {
LegacyRPCMaxClients: defaultRPCMaxClients,
LegacyRPCMaxWebsockets: defaultRPCMaxWebsockets,
DataDir: cfgutil.NewExplicitString(defaultAppDataDir),
UseSPV: false,
AddPeers: []string{},
ConnectPeers: []string{},
MaxPeers: spvchain.MaxPeers,
BanDuration: spvchain.BanDuration,
BanThreshold: spvchain.BanThreshold,
}

// Pre-parse the command line options to see if an alternative config
Expand Down
6 changes: 6 additions & 0 deletions log.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/btcsuite/btcwallet/chain"
"github.com/btcsuite/btcwallet/rpc/legacyrpc"
"github.com/btcsuite/btcwallet/rpc/rpcserver"
"github.com/btcsuite/btcwallet/spvsvc/spvchain"
"github.com/btcsuite/btcwallet/wallet"
"github.com/btcsuite/btcwallet/wtxmgr"
"github.com/btcsuite/seelog"
Expand All @@ -30,6 +31,7 @@ var (
chainLog = btclog.Disabled
grpcLog = btclog.Disabled
legacyRPCLog = btclog.Disabled
spvchainLog = btclog.Disabled
)

// subsystemLoggers maps each subsystem identifier to its associated logger.
Expand All @@ -40,6 +42,7 @@ var subsystemLoggers = map[string]btclog.Logger{
"CHNS": chainLog,
"GRPC": grpcLog,
"RPCS": legacyRPCLog,
"SPVC": spvchainLog,
}

// logClosure is used to provide a closure over expensive logging operations
Expand Down Expand Up @@ -85,6 +88,9 @@ func useLogger(subsystemID string, logger btclog.Logger) {
case "RPCS":
legacyRPCLog = logger
legacyrpc.UseLogger(logger)
case "SPVC":
spvchainLog = logger
spvchain.UseLogger(logger)
}
}

Expand Down
36 changes: 27 additions & 9 deletions rpc/legacyrpc/methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,19 +165,28 @@ type lazyHandler func() (interface{}, *btcjson.RPCError)
// returning a closure that will execute it with the (required) wallet and
// (optional) consensus RPC server. If no handlers are found and the
// chainClient is not nil, the returned handler performs RPC passthrough.
func lazyApplyHandler(request *btcjson.Request, w *wallet.Wallet, chainClient *chain.RPCClient) lazyHandler {
func lazyApplyHandler(request *btcjson.Request, w *wallet.Wallet, chainClient chain.Interface) lazyHandler {
handlerData, ok := rpcHandlers[request.Method]
if ok && handlerData.handlerWithChain != nil && w != nil && chainClient != nil {
return func() (interface{}, *btcjson.RPCError) {
cmd, err := btcjson.UnmarshalCmd(request)
if err != nil {
return nil, btcjson.ErrRPCInvalidRequest
}
resp, err := handlerData.handlerWithChain(cmd, w, chainClient)
if err != nil {
return nil, jsonError(err)
switch client := chainClient.(type) {
case *chain.RPCClient:
resp, err := handlerData.handlerWithChain(cmd,
w, client)
if err != nil {
return nil, jsonError(err)
}
return resp, nil
default:
return nil, &btcjson.RPCError{
Code: -1,
Message: "Chain RPC is inactive",
}
}
return resp, nil
}
}
if ok && handlerData.handler != nil && w != nil {
Expand All @@ -202,11 +211,20 @@ func lazyApplyHandler(request *btcjson.Request, w *wallet.Wallet, chainClient *c
Message: "Chain RPC is inactive",
}
}
resp, err := chainClient.RawRequest(request.Method, request.Params)
if err != nil {
return nil, jsonError(err)
switch client := chainClient.(type) {
case *chain.RPCClient:
resp, err := client.RawRequest(request.Method,
request.Params)
if err != nil {
return nil, jsonError(err)
}
return &resp, nil
default:
return nil, &btcjson.RPCError{
Code: -1,
Message: "Chain RPC is inactive",
}
}
return &resp, nil
}
}

Expand Down
2 changes: 1 addition & 1 deletion rpc/legacyrpc/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ type Server struct {
httpServer http.Server
wallet *wallet.Wallet
walletLoader *wallet.Loader
chainClient *chain.RPCClient
chainClient chain.Interface
handlerLookup func(string) (requestHandler, bool)
handlerMu sync.Mutex

Expand Down
70 changes: 70 additions & 0 deletions spvsvc/spvchain/driver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package spvchain

import (
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcwallet/waddrmgr"
)

// SPVChain is an implementation of the btcwalet chain.Interface interface.
type SPVChain struct {
cs *ChainService
}

// NewSPVChain creates a new SPVChain struct with a backing ChainService
func NewSPVChain(chainService *ChainService) *SPVChain {
return &SPVChain{
cs: chainService,
}
}

// Start replicates the RPC client's Start method.
func (s *SPVChain) Start() error {
s.cs.Start()
return nil
}

// Stop replicates the RPC client's Stop method.
func (s *SPVChain) Stop() {
s.cs.Stop()
}

// WaitForShutdown replicates the RPC client's WaitForShutdown method.
func (s *SPVChain) WaitForShutdown() {
s.cs.Stop()
}

// SendRawTransaction replicates the RPC client's SendRawTransaction command.
func (s *SPVChain) SendRawTransaction(tx *wire.MsgTx, allowHighFees bool) (
*chainhash.Hash, error) {
err := s.cs.SendTransaction(tx)
if err != nil {
return nil, err
}
hash := tx.TxHash()
return &hash, nil
}

// GetBlock replicates the RPC client's GetBlock command.
func (s *SPVChain) GetBlock(hash *chainhash.Hash) (*wire.MsgBlock, error) {
block, err := s.cs.GetBlockFromNetwork(*hash)
if err != nil {
return nil, err
}
return block.MsgBlock(), nil
}

// GetBestBlock replicates the RPC client's GetBestBlock command.
func (s *SPVChain) GetBestBlock() (*chainhash.Hash, int32, error) {
header, height, err := s.cs.LatestBlock()
if err != nil {
return nil, 0, err
}
hash := header.BlockHash()
return &hash, int32(height), nil
}

// BlockStamp replicates the RPC client's BlockStamp command.
func (s *SPVChain) BlockStamp() (*waddrmgr.BlockStamp, error) {
return s.cs.SyncedTo()
}
Loading

0 comments on commit 8af0920

Please sign in to comment.