Use block shas for rescan begin/end.

Also send block sha and block time for rescanprogress/finished.

ok @davecgh
This commit is contained in:
Josh Rickmar 2014-07-17 13:37:54 -05:00
parent a07dadb600
commit 6b8ff7f52f

112
notify.go
View file

@ -11,6 +11,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"sync" "sync"
"time"
"github.com/conformal/btcjson" "github.com/conformal/btcjson"
"github.com/conformal/btcutil" "github.com/conformal/btcutil"
@ -128,12 +129,12 @@ type NotificationHandlers struct {
// signaled on this notification, rather than relying on the return // signaled on this notification, rather than relying on the return
// result of a rescan request, due to how btcd may send various rescan // result of a rescan request, due to how btcd may send various rescan
// notifications after the rescan request has already returned. // notifications after the rescan request has already returned.
OnRescanFinished func(lastProcessedHeight int32) OnRescanFinished func(hash *btcwire.ShaHash, height int32, blkTime time.Time)
// OnRescanProgress is invoked periodically when a rescan is underway. // OnRescanProgress is invoked periodically when a rescan is underway.
// It will only be invoked if a preceding call to Rescan or // It will only be invoked if a preceding call to Rescan or
// RescanEndHeight has been made and the function is non-nil. // RescanEndHeight has been made and the function is non-nil.
OnRescanProgress func(lastProcessedHeight int32) OnRescanProgress func(hash *btcwire.ShaHash, height int32, blkTime time.Time)
// OnTxAccepted is invoked when a transaction is accepted into the // OnTxAccepted is invoked when a transaction is accepted into the
// memory pool. It will only be invoked if a preceding call to // memory pool. It will only be invoked if a preceding call to
@ -262,14 +263,14 @@ func (c *Client) handleNotification(ntfn *rawNotification) {
return return
} }
lastProcessed, err := parseRescanHeightParams(ntfn.Params) hash, height, blkTime, err := parseRescanProgressParams(ntfn.Params)
if err != nil { if err != nil {
log.Warnf("Received invalid rescanfinished "+ log.Warnf("Received invalid rescanfinished "+
"notification: %v", err) "notification: %v", err)
return return
} }
c.ntfnHandlers.OnRescanFinished(lastProcessed) c.ntfnHandlers.OnRescanFinished(hash, height, blkTime)
// OnRescanProgress // OnRescanProgress
case btcws.RescanProgressNtfnMethod: case btcws.RescanProgressNtfnMethod:
@ -279,14 +280,14 @@ func (c *Client) handleNotification(ntfn *rawNotification) {
return return
} }
lastProcessed, err := parseRescanHeightParams(ntfn.Params) hash, height, blkTime, err := parseRescanProgressParams(ntfn.Params)
if err != nil { if err != nil {
log.Warnf("Received invalid rescanprogress "+ log.Warnf("Received invalid rescanprogress "+
"notification: %v", err) "notification: %v", err)
return return
} }
c.ntfnHandlers.OnRescanProgress(lastProcessed) c.ntfnHandlers.OnRescanProgress(hash, height, blkTime)
// OnTxAccepted // OnTxAccepted
case btcws.TxAcceptedNtfnMethod: case btcws.TxAcceptedNtfnMethod:
@ -472,21 +473,41 @@ func parseChainTxNtfnParams(params []json.RawMessage) (*btcutil.Tx,
return btcutil.NewTx(&msgTx), block, nil return btcutil.NewTx(&msgTx), block, nil
} }
// parseRescanHeightParams parses out the height of the last rescanned block // parseRescanProgressParams parses out the height of the last rescanned block
// from the parameters of rescanfinished and rescanprogress notifications. // from the parameters of rescanfinished and rescanprogress notifications.
func parseRescanHeightParams(params []json.RawMessage) (int32, error) { func parseRescanProgressParams(params []json.RawMessage) (*btcwire.ShaHash, int32, time.Time, error) {
if len(params) != 1 { if len(params) != 3 {
return 0, wrongNumParams(len(params)) return nil, 0, time.Time{}, wrongNumParams(len(params))
} }
// Unmarshal first parameter as an integer. // Unmarshal first parameter as an string.
var height int32 var hashStr string
err := json.Unmarshal(params[0], &height) err := json.Unmarshal(params[0], &hashStr)
if err != nil { if err != nil {
return 0, err return nil, 0, time.Time{}, err
} }
return height, nil // Unmarshal second parameter as an integer.
var height int32
err = json.Unmarshal(params[1], &height)
if err != nil {
return nil, 0, time.Time{}, err
}
// Unmarshal third parameter as an integer.
var blkTime int64
err = json.Unmarshal(params[2], &blkTime)
if err != nil {
return nil, 0, time.Time{}, err
}
// Decode string encoding of block hash.
hash, err := btcwire.NewShaHashFromStr(hashStr)
if err != nil {
return nil, 0, time.Time{}, err
}
return hash, height, time.Unix(blkTime, 0), nil
} }
// parseTxAcceptedNtfnParams parses out the transaction hash and total amount // parseTxAcceptedNtfnParams parses out the transaction hash and total amount
@ -929,7 +950,8 @@ func (r FutureRescanResult) Receive() error {
// reconnect. // reconnect.
// //
// NOTE: This is a btcd extension and requires a websocket connection. // NOTE: This is a btcd extension and requires a websocket connection.
func (c *Client) RescanAsync(startHeight int32, addresses []btcutil.Address, func (c *Client) RescanAsync(startBlock *btcwire.ShaHash,
addresses []btcutil.Address,
outpoints []*btcwire.OutPoint) FutureRescanResult { outpoints []*btcwire.OutPoint) FutureRescanResult {
// Not supported in HTTP POST mode. // Not supported in HTTP POST mode.
@ -943,6 +965,12 @@ func (c *Client) RescanAsync(startHeight int32, addresses []btcutil.Address,
return newNilFutureResult() return newNilFutureResult()
} }
// Convert block hashes to strings.
var startBlockShaStr string
if startBlock != nil {
startBlockShaStr = startBlock.String()
}
// Convert addresses to strings. // Convert addresses to strings.
addrs := make([]string, 0, len(addresses)) addrs := make([]string, 0, len(addresses))
for _, addr := range addresses { for _, addr := range addresses {
@ -956,7 +984,7 @@ func (c *Client) RescanAsync(startHeight int32, addresses []btcutil.Address,
} }
id := c.NextID() id := c.NextID()
cmd, err := btcws.NewRescanCmd(id, startHeight, addrs, ops) cmd, err := btcws.NewRescanCmd(id, startBlockShaStr, addrs, ops)
if err != nil { if err != nil {
return newFutureError(err) return newFutureError(err)
} }
@ -964,9 +992,9 @@ func (c *Client) RescanAsync(startHeight int32, addresses []btcutil.Address,
return c.sendCmd(cmd) return c.sendCmd(cmd)
} }
// Rescan rescans the block chain starting from the provided start height to the // Rescan rescans the block chain starting from the provided starting block to
// end of the longest chain for transactions that pay to the passed addresses // the end of the longest chain for transactions that pay to the passed
// and transactions which spend the passed outpoints. // addresses and transactions which spend the passed outpoints.
// //
// The notifications of found transactions are delivered to the notification // The notifications of found transactions are delivered to the notification
// handlers associated with client and this call will not return until the // handlers associated with client and this call will not return until the
@ -980,8 +1008,8 @@ func (c *Client) RescanAsync(startHeight int32, addresses []btcutil.Address,
// to one of the passed addresses), and OnRescanProgress (for rescan progress // to one of the passed addresses), and OnRescanProgress (for rescan progress
// updates). // updates).
// //
// See RescanEndHeight to also specify a block height at which to stop the // See RescanEndBlock to also specify an ending block to finish the rescan
// rescan if a bounded rescan is desired instead. // without continuing through the best block on the main chain.
// //
// NOTE: Rescan requests are not issued on client reconnect and must be // NOTE: Rescan requests are not issued on client reconnect and must be
// performed manually (ideally with a new start height based on the last // performed manually (ideally with a new start height based on the last
@ -990,22 +1018,23 @@ func (c *Client) RescanAsync(startHeight int32, addresses []btcutil.Address,
// reconnect. // reconnect.
// //
// NOTE: This is a btcd extension and requires a websocket connection. // NOTE: This is a btcd extension and requires a websocket connection.
func (c *Client) Rescan(startHeight int32, addresses []btcutil.Address, func (c *Client) Rescan(startBlock *btcwire.ShaHash,
addresses []btcutil.Address,
outpoints []*btcwire.OutPoint) error { outpoints []*btcwire.OutPoint) error {
return c.RescanAsync(startHeight, addresses, outpoints).Receive() return c.RescanAsync(startBlock, addresses, outpoints).Receive()
} }
// RescanEndHeightAsync returns an instance of a type that can be used to get // RescanEndBlockAsync returns an instance of a type that can be used to get
// the result of the RPC at some future time by invoking the Receive function on // the result of the RPC at some future time by invoking the Receive function on
// the returned instance. // the returned instance.
// //
// See RescanEndHeight for the blocking version and more details. // See RescanEndBlock for the blocking version and more details.
// //
// NOTE: This is a btcd extension and requires a websocket connection. // NOTE: This is a btcd extension and requires a websocket connection.
func (c *Client) RescanEndHeightAsync(startHeight int32, func (c *Client) RescanEndBlockAsync(startBlock *btcwire.ShaHash,
addresses []btcutil.Address, outpoints []*btcwire.OutPoint, addresses []btcutil.Address, outpoints []*btcwire.OutPoint,
endHeight int64) FutureRescanResult { endBlock *btcwire.ShaHash) FutureRescanResult {
// Not supported in HTTP POST mode. // Not supported in HTTP POST mode.
if c.config.HttpPostMode { if c.config.HttpPostMode {
@ -1018,6 +1047,15 @@ func (c *Client) RescanEndHeightAsync(startHeight int32,
return newNilFutureResult() return newNilFutureResult()
} }
// Convert block hashes to strings.
var startBlockShaStr, endBlockShaStr string
if startBlock != nil {
startBlockShaStr = startBlock.String()
}
if endBlock != nil {
endBlockShaStr = endBlock.String()
}
// Convert addresses to strings. // Convert addresses to strings.
addrs := make([]string, 0, len(addresses)) addrs := make([]string, 0, len(addresses))
for _, addr := range addresses { for _, addr := range addresses {
@ -1031,7 +1069,8 @@ func (c *Client) RescanEndHeightAsync(startHeight int32,
} }
id := c.NextID() id := c.NextID()
cmd, err := btcws.NewRescanCmd(id, startHeight, addrs, ops, endHeight) cmd, err := btcws.NewRescanCmd(id, startBlockShaStr, addrs, ops,
endBlockShaStr)
if err != nil { if err != nil {
return newFutureError(err) return newFutureError(err)
} }
@ -1039,9 +1078,9 @@ func (c *Client) RescanEndHeightAsync(startHeight int32,
return c.sendCmd(cmd) return c.sendCmd(cmd)
} }
// RescanEndHeight rescans the block chain starting from the provided start // RescanEndBlock rescans the block chain starting from the provided starting
// height up to the provided end height for transactions that pay to the passed // block up to the provided ending block for transactions that pay to the
// addresses and transactions which spend the passed outpoints. // passed addresses and transactions which spend the passed outpoints.
// //
// The notifications of found transactions are delivered to the notification // The notifications of found transactions are delivered to the notification
// handlers associated with client and this call will not return until the // handlers associated with client and this call will not return until the
@ -1058,9 +1097,10 @@ func (c *Client) RescanEndHeightAsync(startHeight int32,
// See Rescan to also perform a rescan through current end of the longest chain. // See Rescan to also perform a rescan through current end of the longest chain.
// //
// NOTE: This is a btcd extension and requires a websocket connection. // NOTE: This is a btcd extension and requires a websocket connection.
func (c *Client) RescanEndHeight(startHeight int32, addresses []btcutil.Address, func (c *Client) RescanEndHeight(startBlock *btcwire.ShaHash,
outpoints []*btcwire.OutPoint, endHeight int64) error { addresses []btcutil.Address, outpoints []*btcwire.OutPoint,
endBlock *btcwire.ShaHash) error {
return c.RescanEndHeightAsync(startHeight, addresses, outpoints, return c.RescanEndBlockAsync(startBlock, addresses, outpoints,
endHeight).Receive() endBlock).Receive()
} }