[NOD-146] Remove unnecessary dag notifications (#288)

This commit is contained in:
Ori Newman 2019-05-06 11:19:19 +03:00 committed by stasatdaglabs
parent 945b3f8fbf
commit 8acc738b27
8 changed files with 1 additions and 1155 deletions

View File

@ -80,23 +80,6 @@ func NewStopNotifyNewTransactionsCmd() *StopNotifyNewTransactionsCmd {
return &StopNotifyNewTransactionsCmd{}
}
// NotifyReceivedCmd defines the notifyReceived JSON-RPC command.
//
// NOTE: Deprecated. Use LoadTxFilterCmd instead.
type NotifyReceivedCmd struct {
Addresses []string
}
// NewNotifyReceivedCmd returns a new instance which can be used to issue a
// notifyReceived JSON-RPC command.
//
// NOTE: Deprecated. Use NewLoadTxFilterCmd instead.
func NewNotifyReceivedCmd(addresses []string) *NotifyReceivedCmd {
return &NotifyReceivedCmd{
Addresses: addresses,
}
}
// OutPoint describes a transaction outpoint that will be marshalled to and
// from JSON.
type OutPoint struct {
@ -128,57 +111,6 @@ func NewLoadTxFilterCmd(reload bool, addresses []string, outPoints []OutPoint) *
}
}
// NotifySpentCmd defines the notifySpent JSON-RPC command.
//
// NOTE: Deprecated. Use LoadTxFilterCmd instead.
type NotifySpentCmd struct {
OutPoints []OutPoint
}
// NewNotifySpentCmd returns a new instance which can be used to issue a
// notifySpent JSON-RPC command.
//
// NOTE: Deprecated. Use NewLoadTxFilterCmd instead.
func NewNotifySpentCmd(outPoints []OutPoint) *NotifySpentCmd {
return &NotifySpentCmd{
OutPoints: outPoints,
}
}
// StopNotifyReceivedCmd defines the stopNotifyReceived JSON-RPC command.
//
// NOTE: Deprecated. Use LoadTxFilterCmd instead.
type StopNotifyReceivedCmd struct {
Addresses []string
}
// NewStopNotifyReceivedCmd returns a new instance which can be used to issue a
// stopNotifyReceived JSON-RPC command.
//
// NOTE: Deprecated. Use NewLoadTxFilterCmd instead.
func NewStopNotifyReceivedCmd(addresses []string) *StopNotifyReceivedCmd {
return &StopNotifyReceivedCmd{
Addresses: addresses,
}
}
// StopNotifySpentCmd defines the stopNotifySpent JSON-RPC command.
//
// NOTE: Deprecated. Use LoadTxFilterCmd instead.
type StopNotifySpentCmd struct {
OutPoints []OutPoint
}
// NewStopNotifySpentCmd returns a new instance which can be used to issue a
// stopNotifySpent JSON-RPC command.
//
// NOTE: Deprecated. Use NewLoadTxFilterCmd instead.
func NewStopNotifySpentCmd(outPoints []OutPoint) *StopNotifySpentCmd {
return &StopNotifySpentCmd{
OutPoints: outPoints,
}
}
// RescanBlocksCmd defines the rescan JSON-RPC command.
//
// NOTE: This is a btcd extension ported from github.com/decred/dcrd/dcrjson
@ -205,12 +137,8 @@ func init() {
MustRegisterCmd("loadTxFilter", (*LoadTxFilterCmd)(nil), flags)
MustRegisterCmd("notifyBlocks", (*NotifyBlocksCmd)(nil), flags)
MustRegisterCmd("notifyNewTransactions", (*NotifyNewTransactionsCmd)(nil), flags)
MustRegisterCmd("notifyReceived", (*NotifyReceivedCmd)(nil), flags)
MustRegisterCmd("notifySpent", (*NotifySpentCmd)(nil), flags)
MustRegisterCmd("session", (*SessionCmd)(nil), flags)
MustRegisterCmd("stopNotifyBlocks", (*StopNotifyBlocksCmd)(nil), flags)
MustRegisterCmd("stopNotifyNewTransactions", (*StopNotifyNewTransactionsCmd)(nil), flags)
MustRegisterCmd("stopNotifySpent", (*StopNotifySpentCmd)(nil), flags)
MustRegisterCmd("stopNotifyReceived", (*StopNotifyReceivedCmd)(nil), flags)
MustRegisterCmd("rescanBlocks", (*RescanBlocksCmd)(nil), flags)
}

View File

@ -114,60 +114,6 @@ func TestDAGSvrWsCmds(t *testing.T) {
marshalled: `{"jsonrpc":"1.0","method":"stopNotifyNewTransactions","params":[],"id":1}`,
unmarshalled: &btcjson.StopNotifyNewTransactionsCmd{},
},
{
name: "notifyReceived",
newCmd: func() (interface{}, error) {
return btcjson.NewCmd("notifyReceived", []string{"1Address"})
},
staticCmd: func() interface{} {
return btcjson.NewNotifyReceivedCmd([]string{"1Address"})
},
marshalled: `{"jsonrpc":"1.0","method":"notifyReceived","params":[["1Address"]],"id":1}`,
unmarshalled: &btcjson.NotifyReceivedCmd{
Addresses: []string{"1Address"},
},
},
{
name: "stopNotifyReceived",
newCmd: func() (interface{}, error) {
return btcjson.NewCmd("stopNotifyReceived", []string{"1Address"})
},
staticCmd: func() interface{} {
return btcjson.NewStopNotifyReceivedCmd([]string{"1Address"})
},
marshalled: `{"jsonrpc":"1.0","method":"stopNotifyReceived","params":[["1Address"]],"id":1}`,
unmarshalled: &btcjson.StopNotifyReceivedCmd{
Addresses: []string{"1Address"},
},
},
{
name: "notifySpent",
newCmd: func() (interface{}, error) {
return btcjson.NewCmd("notifySpent", `[{"txid":"123","index":0}]`)
},
staticCmd: func() interface{} {
ops := []btcjson.OutPoint{{TxID: "123", Index: 0}}
return btcjson.NewNotifySpentCmd(ops)
},
marshalled: `{"jsonrpc":"1.0","method":"notifySpent","params":[[{"txid":"123","index":0}]],"id":1}`,
unmarshalled: &btcjson.NotifySpentCmd{
OutPoints: []btcjson.OutPoint{{TxID: "123", Index: 0}},
},
},
{
name: "stopNotifySpent",
newCmd: func() (interface{}, error) {
return btcjson.NewCmd("stopNotifySpent", `[{"txid":"123","index":0}]`)
},
staticCmd: func() interface{} {
ops := []btcjson.OutPoint{{TxID: "123", Index: 0}}
return btcjson.NewStopNotifySpentCmd(ops)
},
marshalled: `{"jsonrpc":"1.0","method":"stopNotifySpent","params":[[{"txid":"123","index":0}]],"id":1}`,
unmarshalled: &btcjson.StopNotifySpentCmd{
OutPoints: []btcjson.OutPoint{{TxID: "123", Index: 0}},
},
},
{
name: "loadTxFilter",
newCmd: func() (interface{}, error) {

View File

@ -13,36 +13,6 @@ const (
// notifications from the dag server that a block has been connected.
FilteredBlockAddedNtfnMethod = "filteredBlockAdded"
// RecvTxNtfnMethod is the legacy, deprecated method used for
// notifications from the dag server that a transaction which pays to
// a registered address has been processed.
//
// NOTE: Deprecated. Use RelevantTxAcceptedNtfnMethod and
// FilteredBlockAddedNtfnMethod instead.
RecvTxNtfnMethod = "recvTx"
// RedeemingTxNtfnMethod is the legacy, deprecated method used for
// notifications from the dag server that a transaction which spends a
// registered outpoint has been processed.
//
// NOTE: Deprecated. Use RelevantTxAcceptedNtfnMethod and
// FilteredBlockAddedNtfnMethod instead.
RedeemingTxNtfnMethod = "redeemingTx"
// RescanFinishedNtfnMethod is the legacy, deprecated method used for
// notifications from the dag server that a legacy, deprecated rescan
// operation has finished.
//
// NOTE: Deprecated. Not used with rescanblocks command.
RescanFinishedNtfnMethod = "rescanFinished"
// RescanProgressNtfnMethod is the legacy, deprecated method used for
// notifications from the dag server that a legacy, deprecated rescan
// operation this is underway has made progress.
//
// NOTE: Deprecated. Not used with rescanblocks command.
RescanProgressNtfnMethod = "rescanProgress"
// TxAcceptedNtfnMethod is the method used for notifications from the
// dag server that a transaction has been accepted into the mempool.
TxAcceptedNtfnMethod = "txAccepted"
@ -85,90 +55,6 @@ type BlockDetails struct {
Time int64 `json:"time"`
}
// RecvTxNtfn defines the recvTx JSON-RPC notification.
//
// NOTE: Deprecated. Use RelevantTxAcceptedNtfn and FilteredBlockAddedNtfn
// instead.
type RecvTxNtfn struct {
HexTx string
Block *BlockDetails
}
// NewRecvTxNtfn returns a new instance which can be used to issue a recvTx
// JSON-RPC notification.
//
// NOTE: Deprecated. Use NewRelevantTxAcceptedNtfn and
// NewFilteredBlockAddedNtfn instead.
func NewRecvTxNtfn(hexTx string, block *BlockDetails) *RecvTxNtfn {
return &RecvTxNtfn{
HexTx: hexTx,
Block: block,
}
}
// RedeemingTxNtfn defines the redeemingTx JSON-RPC notification.
//
// NOTE: Deprecated. Use RelevantTxAcceptedNtfn and FilteredBlockAddedNtfn
// instead.
type RedeemingTxNtfn struct {
HexTx string
Block *BlockDetails
}
// NewRedeemingTxNtfn returns a new instance which can be used to issue a
// redeemingTx JSON-RPC notification.
//
// NOTE: Deprecated. Use NewRelevantTxAcceptedNtfn and
// NewFilteredBlockAddedNtfn instead.
func NewRedeemingTxNtfn(hexTx string, block *BlockDetails) *RedeemingTxNtfn {
return &RedeemingTxNtfn{
HexTx: hexTx,
Block: block,
}
}
// RescanFinishedNtfn defines the rescanFinished JSON-RPC notification.
//
// NOTE: Deprecated. Not used with rescanblocks command.
type RescanFinishedNtfn struct {
Hash string
Height uint64
Time int64
}
// NewRescanFinishedNtfn returns a new instance which can be used to issue a
// rescanFinished JSON-RPC notification.
//
// NOTE: Deprecated. Not used with rescanblocks command.
func NewRescanFinishedNtfn(hash string, height uint64, time int64) *RescanFinishedNtfn {
return &RescanFinishedNtfn{
Hash: hash,
Height: height,
Time: time,
}
}
// RescanProgressNtfn defines the rescanProgress JSON-RPC notification.
//
// NOTE: Deprecated. Not used with rescanblocks command.
type RescanProgressNtfn struct {
Hash string
Height uint64
Time int64
}
// NewRescanProgressNtfn returns a new instance which can be used to issue a
// rescanProgress JSON-RPC notification.
//
// NOTE: Deprecated. Not used with rescanblocks command.
func NewRescanProgressNtfn(hash string, height uint64, time int64) *RescanProgressNtfn {
return &RescanProgressNtfn{
Hash: hash,
Height: height,
Time: time,
}
}
// TxAcceptedNtfn defines the txAccepted JSON-RPC notification.
type TxAcceptedNtfn struct {
TxID string
@ -215,10 +101,6 @@ func init() {
flags := UFWebsocketOnly | UFNotification
MustRegisterCmd(FilteredBlockAddedNtfnMethod, (*FilteredBlockAddedNtfn)(nil), flags)
MustRegisterCmd(RecvTxNtfnMethod, (*RecvTxNtfn)(nil), flags)
MustRegisterCmd(RedeemingTxNtfnMethod, (*RedeemingTxNtfn)(nil), flags)
MustRegisterCmd(RescanFinishedNtfnMethod, (*RescanFinishedNtfn)(nil), flags)
MustRegisterCmd(RescanProgressNtfnMethod, (*RescanProgressNtfn)(nil), flags)
MustRegisterCmd(TxAcceptedNtfnMethod, (*TxAcceptedNtfn)(nil), flags)
MustRegisterCmd(TxAcceptedVerboseNtfnMethod, (*TxAcceptedVerboseNtfn)(nil), flags)
MustRegisterCmd(RelevantTxAcceptedNtfnMethod, (*RelevantTxAcceptedNtfn)(nil), flags)

View File

@ -47,86 +47,6 @@ func TestDAGSvrWsNtfns(t *testing.T) {
SubscribedTxs: []string{"tx0", "tx1"},
},
},
{
name: "recvTx",
newNtfn: func() (interface{}, error) {
return btcjson.NewCmd("recvTx", "001122", `{"height":100000,"hash":"123","index":0,"time":12345678}`)
},
staticNtfn: func() interface{} {
blockDetails := btcjson.BlockDetails{
Height: 100000,
Hash: "123",
Index: 0,
Time: 12345678,
}
return btcjson.NewRecvTxNtfn("001122", &blockDetails)
},
marshalled: `{"jsonrpc":"1.0","method":"recvTx","params":["001122",{"height":100000,"hash":"123","index":0,"time":12345678}],"id":null}`,
unmarshalled: &btcjson.RecvTxNtfn{
HexTx: "001122",
Block: &btcjson.BlockDetails{
Height: 100000,
Hash: "123",
Index: 0,
Time: 12345678,
},
},
},
{
name: "redeemingTx",
newNtfn: func() (interface{}, error) {
return btcjson.NewCmd("redeemingTx", "001122", `{"height":100000,"hash":"123","index":0,"time":12345678}`)
},
staticNtfn: func() interface{} {
blockDetails := btcjson.BlockDetails{
Height: 100000,
Hash: "123",
Index: 0,
Time: 12345678,
}
return btcjson.NewRedeemingTxNtfn("001122", &blockDetails)
},
marshalled: `{"jsonrpc":"1.0","method":"redeemingTx","params":["001122",{"height":100000,"hash":"123","index":0,"time":12345678}],"id":null}`,
unmarshalled: &btcjson.RedeemingTxNtfn{
HexTx: "001122",
Block: &btcjson.BlockDetails{
Height: 100000,
Hash: "123",
Index: 0,
Time: 12345678,
},
},
},
{
name: "rescanFinished",
newNtfn: func() (interface{}, error) {
return btcjson.NewCmd("rescanFinished", "123", 100000, 12345678)
},
staticNtfn: func() interface{} {
return btcjson.NewRescanFinishedNtfn("123", 100000, 12345678)
},
marshalled: `{"jsonrpc":"1.0","method":"rescanFinished","params":["123",100000,12345678],"id":null}`,
unmarshalled: &btcjson.RescanFinishedNtfn{
Hash: "123",
Height: 100000,
Time: 12345678,
},
},
{
name: "rescanProgress",
newNtfn: func() (interface{}, error) {
return btcjson.NewCmd("rescanProgress", "123", 100000, 12345678)
},
staticNtfn: func() interface{} {
return btcjson.NewRescanProgressNtfn("123", 100000, 12345678)
},
marshalled: `{"jsonrpc":"1.0","method":"rescanProgress","params":["123",100000,12345678],"id":null}`,
unmarshalled: &btcjson.RescanProgressNtfn{
Hash: "123",
Height: 100000,
Time: 12345678,
},
},
{
name: "txAccepted",
newNtfn: func() (interface{}, error) {

View File

@ -261,16 +261,6 @@ func (c *Client) trackRegisteredNtfns(cmd interface{}) {
c.ntfnState.notifyNewTx = true
}
c.ntfnState.notifyNewTxSubnetworkID = bcmd.Subnetwork
case *btcjson.NotifySpentCmd:
for _, op := range bcmd.OutPoints {
c.ntfnState.notifySpent[op] = struct{}{}
}
case *btcjson.NotifyReceivedCmd:
for _, addr := range bcmd.Addresses {
c.ntfnState.notifyReceived[addr] = struct{}{}
}
}
}
@ -536,34 +526,6 @@ func (c *Client) reregisterNtfns() error {
}
}
// Reregister the combination of all previously registered notifyspent
// outpoints in one command if needed.
nslen := len(stateCopy.notifySpent)
if nslen > 0 {
outpoints := make([]btcjson.OutPoint, 0, nslen)
for op := range stateCopy.notifySpent {
outpoints = append(outpoints, op)
}
log.Debugf("Reregistering [notifyspent] outpoints: %v", outpoints)
if err := c.notifySpentInternal(outpoints).Receive(); err != nil {
return err
}
}
// Reregister the combination of all previously registered
// notifyreceived addresses in one command if needed.
nrlen := len(stateCopy.notifyReceived)
if nrlen > 0 {
addresses := make([]string, 0, nrlen)
for addr := range stateCopy.notifyReceived {
addresses = append(addresses, addr)
}
log.Debugf("Reregistering [notifyreceived] addresses: %v", addresses)
if err := c.notifyReceivedInternal(addresses).Receive(); err != nil {
return err
}
}
return nil
}

View File

@ -36,8 +36,6 @@ type notificationState struct {
notifyNewTx bool
notifyNewTxVerbose bool
notifyNewTxSubnetworkID *string
notifyReceived map[string]struct{}
notifySpent map[btcjson.OutPoint]struct{}
}
// Copy returns a deep copy of the receiver.
@ -47,24 +45,13 @@ func (s *notificationState) Copy() *notificationState {
stateCopy.notifyNewTx = s.notifyNewTx
stateCopy.notifyNewTxVerbose = s.notifyNewTxVerbose
stateCopy.notifyNewTxSubnetworkID = s.notifyNewTxSubnetworkID
stateCopy.notifyReceived = make(map[string]struct{})
for addr := range s.notifyReceived {
stateCopy.notifyReceived[addr] = struct{}{}
}
stateCopy.notifySpent = make(map[btcjson.OutPoint]struct{})
for op := range s.notifySpent {
stateCopy.notifySpent[op] = struct{}{}
}
return &stateCopy
}
// newNotificationState returns a new notification state ready to be populated.
func newNotificationState() *notificationState {
return &notificationState{
notifyReceived: make(map[string]struct{}),
notifySpent: make(map[btcjson.OutPoint]struct{}),
}
return &notificationState{}
}
// newNilFutureResult returns a new future result channel that already has the
@ -81,11 +68,6 @@ func newNilFutureResult() chan *response {
// notifications. Since all of the functions are nil by default, all
// notifications are effectively ignored until their handlers are set to a
// concrete callback.
//
// NOTE: Unless otherwise documented, these handlers must NOT directly call any
// blocking calls on the client instance since the input reader goroutine blocks
// until the callback has completed. Doing so will result in a deadlock
// situation.
type NotificationHandlers struct {
// OnClientConnected is invoked when the client connects or reconnects
// to the RPC server. This callback is run async with the rest of the
@ -107,29 +89,6 @@ type NotificationHandlers struct {
OnFilteredBlockAdded func(height uint64, header *wire.BlockHeader,
txs []*util.Tx)
// OnRecvTx is invoked when a transaction that receives funds to a
// registered address is received into the memory pool and also
// connected to the BlockDAG. It will only be invoked if a
// preceding call to NotifyReceived, Rescan, or RescanEndHeight has been
// made to register for the notification and the function is non-nil.
//
// NOTE: Deprecated. Use OnRelevantTxAccepted instead.
OnRecvTx func(transaction *util.Tx, details *btcjson.BlockDetails)
// OnRedeemingTx is invoked when a transaction that spends a registered
// outpoint is received into the memory pool and also connected to the
// blockDAG. It will only be invoked if a preceding call to
// NotifySpent, Rescan, or RescanEndHeight has been made to register for
// the notification and the function is non-nil.
//
// NOTE: The NotifyReceived will automatically register notifications
// for the outpoints that are now "owned" as a result of receiving
// funds to the registered addresses. This means it is possible for
// this to invoked indirectly as the result of a NotifyReceived call.
//
// NOTE: Deprecated. Use OnRelevantTxAccepted instead.
OnRedeemingTx func(transaction *util.Tx, details *btcjson.BlockDetails)
// OnRelevantTxAccepted is invoked when an unmined transaction passes
// the client's transaction filter.
//
@ -137,22 +96,6 @@ type NotificationHandlers struct {
// github.com/decred/dcrrpcclient.
OnRelevantTxAccepted func(transaction []byte)
// OnRescanFinished is invoked after a rescan finishes due to a previous
// call to Rescan or RescanEndHeight. Finished rescans should be
// signaled on this notification, rather than relying on the return
// result of a rescan request, due to how btcd may send various rescan
// notifications after the rescan request has already returned.
//
// NOTE: Deprecated. Not used with RescanBlocks.
OnRescanFinished func(hash *daghash.Hash, height int32, blkTime time.Time)
// OnRescanProgress is invoked periodically when a rescan is underway.
// It will only be invoked if a preceding call to Rescan or
// RescanEndHeight has been made and the function is non-nil.
//
// NOTE: Deprecated. Not used with RescanBlocks.
OnRescanProgress func(hash *daghash.Hash, height int32, blkTime time.Time)
// OnTxAccepted is invoked when a transaction is accepted into the
// memory pool. It will only be invoked if a preceding call to
// NotifyNewTransactions with the verbose flag set to false has been
@ -224,40 +167,6 @@ func (c *Client) handleNotification(ntfn *rawNotification) {
c.ntfnHandlers.OnFilteredBlockAdded(blockHeight,
blockHeader, transactions)
// OnRecvTx
case btcjson.RecvTxNtfnMethod:
// Ignore the notification if the client is not interested in
// it.
if c.ntfnHandlers.OnRecvTx == nil {
return
}
tx, block, err := parseChainTxNtfnParams(ntfn.Params)
if err != nil {
log.Warnf("Received invalid recvtx notification: %s",
err)
return
}
c.ntfnHandlers.OnRecvTx(tx, block)
// OnRedeemingTx
case btcjson.RedeemingTxNtfnMethod:
// Ignore the notification if the client is not interested in
// it.
if c.ntfnHandlers.OnRedeemingTx == nil {
return
}
tx, block, err := parseChainTxNtfnParams(ntfn.Params)
if err != nil {
log.Warnf("Received invalid redeemingtx "+
"notification: %s", err)
return
}
c.ntfnHandlers.OnRedeemingTx(tx, block)
// OnRelevantTxAccepted
case btcjson.RelevantTxAcceptedNtfnMethod:
// Ignore the notification if the client is not interested in
@ -275,40 +184,6 @@ func (c *Client) handleNotification(ntfn *rawNotification) {
c.ntfnHandlers.OnRelevantTxAccepted(transaction)
// OnRescanFinished
case btcjson.RescanFinishedNtfnMethod:
// Ignore the notification if the client is not interested in
// it.
if c.ntfnHandlers.OnRescanFinished == nil {
return
}
hash, height, blkTime, err := parseRescanProgressParams(ntfn.Params)
if err != nil {
log.Warnf("Received invalid rescanfinished "+
"notification: %s", err)
return
}
c.ntfnHandlers.OnRescanFinished(hash, height, blkTime)
// OnRescanProgress
case btcjson.RescanProgressNtfnMethod:
// Ignore the notification if the client is not interested in
// it.
if c.ntfnHandlers.OnRescanProgress == nil {
return
}
hash, height, blkTime, err := parseRescanProgressParams(ntfn.Params)
if err != nil {
log.Warnf("Received invalid rescanprogress "+
"notification: %s", err)
return
}
c.ntfnHandlers.OnRescanProgress(hash, height, blkTime)
// OnTxAccepted
case btcjson.TxAcceptedNtfnMethod:
// Ignore the notification if the client is not interested in
@ -578,43 +453,6 @@ func parseChainTxNtfnParams(params []json.RawMessage) (*util.Tx,
return util.NewTx(&msgTx), block, nil
}
// parseRescanProgressParams parses out the height of the last rescanned block
// from the parameters of rescanfinished and rescanprogress notifications.
func parseRescanProgressParams(params []json.RawMessage) (*daghash.Hash, int32, time.Time, error) {
if len(params) != 3 {
return nil, 0, time.Time{}, wrongNumParams(len(params))
}
// Unmarshal first parameter as an string.
var hashStr string
err := json.Unmarshal(params[0], &hashStr)
if err != nil {
return nil, 0, time.Time{}, err
}
// 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 := daghash.NewHashFromStr(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
// from the parameters of a txaccepted notification.
func parseTxAcceptedNtfnParams(params []json.RawMessage) (*daghash.Hash,
@ -801,38 +639,6 @@ func (c *Client) NotifyBlocks() error {
return c.NotifyBlocksAsync().Receive()
}
// FutureNotifySpentResult is a future promise to deliver the result of a
// NotifySpentAsync RPC invocation (or an applicable error).
//
// NOTE: Deprecated. Use FutureLoadTxFilterResult instead.
type FutureNotifySpentResult chan *response
// Receive waits for the response promised by the future and returns an error
// if the registration was not successful.
func (r FutureNotifySpentResult) Receive() error {
_, err := receiveFuture(r)
return err
}
// notifySpentInternal is the same as notifySpentAsync except it accepts
// the converted outpoints as a parameter so the client can more efficiently
// recreate the previous notification state on reconnect.
func (c *Client) notifySpentInternal(outpoints []btcjson.OutPoint) FutureNotifySpentResult {
// Not supported in HTTP POST mode.
if c.config.HTTPPostMode {
return newFutureError(ErrWebsocketsRequired)
}
// Ignore the notification if the client is not interested in
// notifications.
if c.ntfnHandlers == nil {
return newNilFutureResult()
}
cmd := btcjson.NewNotifySpentCmd(outpoints)
return c.sendCmd(cmd)
}
// newOutPointFromWire constructs the btcjson representation of a transaction
// outpoint from the wire type.
func newOutPointFromWire(op *wire.OutPoint) btcjson.OutPoint {
@ -842,51 +648,6 @@ func newOutPointFromWire(op *wire.OutPoint) btcjson.OutPoint {
}
}
// NotifySpentAsync 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 returned instance.
//
// See NotifySpent for the blocking version and more details.
//
// NOTE: This is a btcd extension and requires a websocket connection.
//
// NOTE: Deprecated. Use LoadTxFilterAsync instead.
func (c *Client) NotifySpentAsync(outpoints []*wire.OutPoint) FutureNotifySpentResult {
// Not supported in HTTP POST mode.
if c.config.HTTPPostMode {
return newFutureError(ErrWebsocketsRequired)
}
// Ignore the notification if the client is not interested in
// notifications.
if c.ntfnHandlers == nil {
return newNilFutureResult()
}
ops := make([]btcjson.OutPoint, 0, len(outpoints))
for _, outpoint := range outpoints {
ops = append(ops, newOutPointFromWire(outpoint))
}
cmd := btcjson.NewNotifySpentCmd(ops)
return c.sendCmd(cmd)
}
// NotifySpent registers the client to receive notifications when the passed
// transaction outputs are spent. The notifications are delivered to the
// notification handlers associated with the client. Calling this function has
// no effect if there are no notification handlers and will result in an error
// if the client is configured to run in HTTP POST mode.
//
// The notifications delivered as a result of this call will be via
// OnRedeemingTx.
//
// NOTE: This is a btcd extension and requires a websocket connection.
//
// NOTE: Deprecated. Use LoadTxFilter instead.
func (c *Client) NotifySpent(outpoints []*wire.OutPoint) error {
return c.NotifySpentAsync(outpoints).Receive()
}
// FutureNotifyNewTransactionsResult is a future promise to deliver the result
// of a NotifyNewTransactionsAsync RPC invocation (or an applicable error).
type FutureNotifyNewTransactionsResult chan *response
@ -936,105 +697,6 @@ func (c *Client) NotifyNewTransactions(verbose bool, subnetworkID *string) error
return c.NotifyNewTransactionsAsync(verbose, subnetworkID).Receive()
}
// FutureNotifyReceivedResult is a future promise to deliver the result of a
// NotifyReceivedAsync RPC invocation (or an applicable error).
//
// NOTE: Deprecated. Use FutureLoadTxFilterResult instead.
type FutureNotifyReceivedResult chan *response
// Receive waits for the response promised by the future and returns an error
// if the registration was not successful.
func (r FutureNotifyReceivedResult) Receive() error {
_, err := receiveFuture(r)
return err
}
// notifyReceivedInternal is the same as notifyReceivedAsync except it accepts
// the converted addresses as a parameter so the client can more efficiently
// recreate the previous notification state on reconnect.
func (c *Client) notifyReceivedInternal(addresses []string) FutureNotifyReceivedResult {
// Not supported in HTTP POST mode.
if c.config.HTTPPostMode {
return newFutureError(ErrWebsocketsRequired)
}
// Ignore the notification if the client is not interested in
// notifications.
if c.ntfnHandlers == nil {
return newNilFutureResult()
}
// Convert addresses to strings.
cmd := btcjson.NewNotifyReceivedCmd(addresses)
return c.sendCmd(cmd)
}
// NotifyReceivedAsync 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 returned instance.
//
// See NotifyReceived for the blocking version and more details.
//
// NOTE: This is a btcd extension and requires a websocket connection.
//
// NOTE: Deprecated. Use LoadTxFilterAsync instead.
func (c *Client) NotifyReceivedAsync(addresses []util.Address) FutureNotifyReceivedResult {
// Not supported in HTTP POST mode.
if c.config.HTTPPostMode {
return newFutureError(ErrWebsocketsRequired)
}
// Ignore the notification if the client is not interested in
// notifications.
if c.ntfnHandlers == nil {
return newNilFutureResult()
}
// Convert addresses to strings.
addrs := make([]string, 0, len(addresses))
for _, addr := range addresses {
addrs = append(addrs, addr.String())
}
cmd := btcjson.NewNotifyReceivedCmd(addrs)
return c.sendCmd(cmd)
}
// NotifyReceived registers the client to receive notifications every time a
// new transaction which pays to one of the passed addresses is accepted to
// memory pool or in a block added to the block DAG. In addition, when
// one of these transactions is detected, the client is also automatically
// registered for notifications when the new transaction outpoints the address
// now has available are spent (See NotifySpent). The notifications are
// delivered to the notification handlers associated with the client. Calling
// this function has no effect if there are no notification handlers and will
// result in an error if the client is configured to run in HTTP POST mode.
//
// The notifications delivered as a result of this call will be via one of
// *OnRecvTx (for transactions that receive funds to one of the passed
// addresses) or OnRedeemingTx (for transactions which spend from one
// of the outpoints which are automatically registered upon receipt of funds to
// the address).
//
// NOTE: This is a btcd extension and requires a websocket connection.
//
// NOTE: Deprecated. Use LoadTxFilter instead.
func (c *Client) NotifyReceived(addresses []util.Address) error {
return c.NotifyReceivedAsync(addresses).Receive()
}
// FutureRescanResult is a future promise to deliver the result of a RescanAsync
// or RescanEndHeightAsync RPC invocation (or an applicable error).
//
// NOTE: Deprecated. Use FutureRescanBlocksResult instead.
type FutureRescanResult chan *response
// Receive waits for the response promised by the future and returns an error
// if the rescan was not successful.
func (r FutureRescanResult) Receive() error {
_, err := receiveFuture(r)
return err
}
// FutureLoadTxFilterResult is a future promise to deliver the result
// of a LoadTxFilterAsync RPC invocation (or an applicable error).
//

View File

@ -610,43 +610,16 @@ var helpDescsEnUS = map[string]string{
// StopNotifyNewTransactionsCmd help.
"stopNotifyNewTransactions--synopsis": "Stop sending either a txaccepted or a txacceptedverbose notification when a new transaction is accepted into the mempool.",
// NotifyReceivedCmd help.
"notifyReceived--synopsis": "Send a recvtx notification when a transaction added to mempool or appears in a newly-attached block contains a txout pkScript sending to any of the passed addresses.\n" +
"Matching outpoints are automatically registered for redeemingtx notifications.",
"notifyReceived-addresses": "List of address to receive notifications about",
// StopNotifyReceivedCmd help.
"stopNotifyReceived--synopsis": "Cancel registered receive notifications for each passed address.",
"stopNotifyReceived-addresses": "List of address to cancel receive notifications for",
// OutPoint help.
"outPoint-txid": "The hex-encoded bytes of the outPoint transaction ID",
"outPoint-index": "The index of the outPoint",
// NotifySpentCmd help.
"notifySpent--synopsis": "Send a redeemingtx notification when a transaction spending an outPoint appears in mempool (if relayed to this btcd instance) and when such a transaction first appears in a newly-attached block.",
"notifySpent-outPoints": "List of transaction outpoints to monitor.",
// StopNotifySpentCmd help.
"stopNotifySpent--synopsis": "Cancel registered spending notifications for each passed outPoint.",
"stopNotifySpent-outPoints": "List of transaction outpoints to stop monitoring.",
// LoadTxFilterCmd help.
"loadTxFilter--synopsis": "Load, add to, or reload a websocket client's transaction filter for mempool transactions, new blocks and rescanBlocks.",
"loadTxFilter-reload": "Load a new filter instead of adding data to an existing one",
"loadTxFilter-addresses": "Array of addresses to add to the transaction filter",
"loadTxFilter-outPoints": "Array of outpoints to add to the transaction filter",
// Rescan help.
"rescan--synopsis": "Rescan block chain for transactions to addresses.\n" +
"When the endblock parameter is omitted, the rescan continues through the best block in the main chain.\n" +
"Rescan results are sent as recvtx and redeemingtx notifications.\n" +
"This call returns once the rescan completes.",
"rescan-beginBlock": "Hash of the first block to begin rescanning",
"rescan-addresses": "List of addresses to include in the rescan",
"rescan-outPoints": "List of transaction outpoints to include in the rescan",
"rescan-endBlock": "Hash of final block to rescan",
// RescanBlocks help.
"rescanBlocks--synopsis": "Rescan blocks for transactions matching the loaded transaction filter.",
"rescanBlocks-blockHashes": "List of hashes to rescan. Each next block must be a child of the previous.",
@ -742,11 +715,6 @@ var rpcResultTypes = map[string][]interface{}{
"stopNotifyBlocks": nil,
"notifyNewTransactions": nil,
"stopNotifyNewTransactions": nil,
"notifyReceived": nil,
"stopNotifyReceived": nil,
"notifySpent": nil,
"stopNotifySpent": nil,
"rescan": nil,
"rescanBlocks": {(*[]btcjson.RescannedBlock)(nil)},
}

View File

@ -69,13 +69,9 @@ var wsHandlersBeforeInit = map[string]wsCommandHandler{
"help": handleWebsocketHelp,
"notifyBlocks": handleNotifyBlocks,
"notifyNewTransactions": handleNotifyNewTransactions,
"notifyReceived": handleNotifyReceived,
"notifySpent": handleNotifySpent,
"session": handleSession,
"stopNotifyBlocks": handleStopNotifyBlocks,
"stopNotifyNewTransactions": handleStopNotifyNewTransactions,
"stopNotifySpent": handleStopNotifySpent,
"stopNotifyReceived": handleStopNotifyReceived,
"rescanBlocks": handleRescanBlocks,
}
@ -446,22 +442,6 @@ type notificationRegisterBlocks wsClient
type notificationUnregisterBlocks wsClient
type notificationRegisterNewMempoolTxs wsClient
type notificationUnregisterNewMempoolTxs wsClient
type notificationRegisterSpent struct {
wsc *wsClient
ops []*wire.OutPoint
}
type notificationUnregisterSpent struct {
wsc *wsClient
op *wire.OutPoint
}
type notificationRegisterAddr struct {
wsc *wsClient
addrs []string
}
type notificationUnregisterAddr struct {
wsc *wsClient
addr string
}
// notificationHandler reads notifications and control messages from the queue
// handler and processes one at a time.
@ -478,8 +458,6 @@ func (m *wsNotificationManager) notificationHandler() {
// since it is quite a bit more efficient than using the entire struct.
blockNotifications := make(map[chan struct{}]*wsClient)
txNotifications := make(map[chan struct{}]*wsClient)
watchedOutPoints := make(map[wire.OutPoint]map[chan struct{}]*wsClient)
watchedAddrs := make(map[string]map[chan struct{}]*wsClient)
out:
for {
@ -493,15 +471,6 @@ out:
case *notificationBlockAdded:
block := (*util.Block)(n)
// Skip iterating through all txs if no
// tx notification requests exist.
if len(watchedOutPoints) != 0 || len(watchedAddrs) != 0 {
for _, tx := range block.Transactions() {
m.notifyForTx(watchedOutPoints,
watchedAddrs, tx, block)
}
}
if len(blockNotifications) != 0 {
m.notifyFilteredBlockAdded(blockNotifications,
block)
@ -511,7 +480,6 @@ out:
if n.isNew && len(txNotifications) != 0 {
m.notifyForNewTx(txNotifications, n.tx)
}
m.notifyForTx(watchedOutPoints, watchedAddrs, n.tx, nil)
m.notifyRelevantTxAccepted(n.tx, clients)
case *notificationRegisterBlocks:
@ -532,27 +500,8 @@ out:
// the client itself.
delete(blockNotifications, wsc.quit)
delete(txNotifications, wsc.quit)
for k := range wsc.spentRequests {
op := k
m.removeSpentRequest(watchedOutPoints, wsc, &op)
}
for addr := range wsc.addrRequests {
m.removeAddrRequest(watchedAddrs, wsc, addr)
}
delete(clients, wsc.quit)
case *notificationRegisterSpent:
m.addSpentRequests(watchedOutPoints, n.wsc, n.ops)
case *notificationUnregisterSpent:
m.removeSpentRequest(watchedOutPoints, n.wsc, n.op)
case *notificationRegisterAddr:
m.addAddrRequests(watchedAddrs, n.wsc, n.addrs)
case *notificationUnregisterAddr:
m.removeAddrRequest(watchedAddrs, n.wsc, n.addr)
case *notificationRegisterNewMempoolTxs:
wsc := (*wsClient)(n)
txNotifications[wsc.quit] = wsc
@ -800,91 +749,6 @@ func (m *wsNotificationManager) notifyForNewTx(clients map[chan struct{}]*wsClie
}
}
// RegisterSpentRequests requests a notification when each of the passed
// outpoints is confirmed spent (contained in a block added to the blockDAG)
// for the passed websocket client. The request is automatically
// removed once the notification has been sent.
func (m *wsNotificationManager) RegisterSpentRequests(wsc *wsClient, ops []*wire.OutPoint) {
m.queueNotification <- &notificationRegisterSpent{
wsc: wsc,
ops: ops,
}
}
// addSpentRequests modifies a map of watched outpoints to sets of websocket
// clients to add a new request watch all of the outpoints in ops and create
// and send a notification when spent to the websocket client wsc.
func (m *wsNotificationManager) addSpentRequests(opMap map[wire.OutPoint]map[chan struct{}]*wsClient,
wsc *wsClient, ops []*wire.OutPoint) {
for _, op := range ops {
// Track the request in the client as well so it can be quickly
// be removed on disconnect.
wsc.spentRequests[*op] = struct{}{}
// Add the client to the list to notify when the outpoint is seen.
// Create the list as needed.
cmap, ok := opMap[*op]
if !ok {
cmap = make(map[chan struct{}]*wsClient)
opMap[*op] = cmap
}
cmap[wsc.quit] = wsc
}
// Check if any transactions spending these outputs already exists in
// the mempool, if so send the notification immediately.
spends := make(map[daghash.Hash]*util.Tx)
for _, op := range ops {
spend := m.server.cfg.TxMemPool.CheckSpend(*op)
if spend != nil {
log.Debugf("Found existing mempool spend for "+
"outpoint<%s>: %s", op, spend.Hash())
spends[*spend.Hash()] = spend
}
}
for _, spend := range spends {
m.notifyForTx(opMap, nil, spend, nil)
}
}
// UnregisterSpentRequest removes a request from the passed websocket client
// to be notified when the passed outpoint is confirmed spent (contained in a
// block added to the blockDAG).
func (m *wsNotificationManager) UnregisterSpentRequest(wsc *wsClient, op *wire.OutPoint) {
m.queueNotification <- &notificationUnregisterSpent{
wsc: wsc,
op: op,
}
}
// removeSpentRequest modifies a map of watched outpoints to remove the
// websocket client wsc from the set of clients to be notified when a
// watched outpoint is spent. If wsc is the last client, the outpoint
// key is removed from the map.
func (*wsNotificationManager) removeSpentRequest(ops map[wire.OutPoint]map[chan struct{}]*wsClient,
wsc *wsClient, op *wire.OutPoint) {
// Remove the request tracking from the client.
delete(wsc.spentRequests, *op)
// Remove the client from the list to notify.
notifyMap, ok := ops[*op]
if !ok {
log.Warnf("Attempt to remove nonexistent spent request "+
"for websocket client %s", wsc.addr)
return
}
delete(notifyMap, wsc.quit)
// Remove the map entry altogether if there are
// no more clients interested in it.
if len(notifyMap) == 0 {
delete(ops, *op)
}
}
// txHexString returns the serialized transaction encoded in hexadecimal.
func txHexString(tx *wire.MsgTx) string {
buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
@ -907,66 +771,6 @@ func blockDetails(block *util.Block, txIndex int) *btcjson.BlockDetails {
}
}
// newRedeemingTxNotification returns a new marshalled redeemingtx notification
// with the passed parameters.
func newRedeemingTxNotification(txHex string, index int, block *util.Block) ([]byte, error) {
// Create and marshal the notification.
ntfn := btcjson.NewRedeemingTxNtfn(txHex, blockDetails(block, index))
return btcjson.MarshalCmd(nil, ntfn)
}
// notifyForTxOuts examines each transaction output, notifying interested
// websocket clients of the transaction if an output spends to a watched
// address. A spent notification request is automatically registered for
// the client for each matching output.
func (m *wsNotificationManager) notifyForTxOuts(ops map[wire.OutPoint]map[chan struct{}]*wsClient,
addrs map[string]map[chan struct{}]*wsClient, tx *util.Tx, block *util.Block) {
// Nothing to do if nobody is listening for address notifications.
if len(addrs) == 0 {
return
}
txHex := ""
wscNotified := make(map[chan struct{}]struct{})
for i, txOut := range tx.MsgTx().TxOut {
_, txAddrs, _, err := txscript.ExtractPkScriptAddrs(
txOut.PkScript, m.server.cfg.DAGParams)
if err != nil {
continue
}
for _, txAddr := range txAddrs {
cmap, ok := addrs[txAddr.EncodeAddress()]
if !ok {
continue
}
if txHex == "" {
txHex = txHexString(tx.MsgTx())
}
ntfn := btcjson.NewRecvTxNtfn(txHex, blockDetails(block,
tx.Index()))
marshalledJSON, err := btcjson.MarshalCmd(nil, ntfn)
if err != nil {
log.Errorf("Failed to marshal processedtx notification: %s", err)
continue
}
op := []*wire.OutPoint{wire.NewOutPoint(tx.ID(), uint32(i))}
for wscQuit, wsc := range cmap {
m.addSpentRequests(ops, wsc, op)
if _, ok := wscNotified[wscQuit]; !ok {
wscNotified[wscQuit] = struct{}{}
wsc.QueueNotification(marshalledJSON)
}
}
}
}
}
// notifyRelevantTxAccepted examines the inputs and outputs of the passed
// transaction, notifying websocket clients of outputs spending to a watched
// address and inputs spending a watched outpoint. Any outputs paying to a
@ -990,124 +794,6 @@ func (m *wsNotificationManager) notifyRelevantTxAccepted(tx *util.Tx,
}
}
// notifyForTx examines the inputs and outputs of the passed transaction,
// notifying websocket clients of outputs spending to a watched address
// and inputs spending a watched outpoint.
func (m *wsNotificationManager) notifyForTx(ops map[wire.OutPoint]map[chan struct{}]*wsClient,
addrs map[string]map[chan struct{}]*wsClient, tx *util.Tx, block *util.Block) {
if len(ops) != 0 {
m.notifyForTxIns(ops, tx, block)
}
if len(addrs) != 0 {
m.notifyForTxOuts(ops, addrs, tx, block)
}
}
// notifyForTxIns examines the inputs of the passed transaction and sends
// interested websocket clients a redeemingtx notification if any inputs
// spend a watched output. If block is non-nil, any matching spent
// requests are removed.
func (m *wsNotificationManager) notifyForTxIns(ops map[wire.OutPoint]map[chan struct{}]*wsClient,
tx *util.Tx, block *util.Block) {
// Nothing to do if nobody is watching outpoints.
if len(ops) == 0 {
return
}
txHex := ""
wscNotified := make(map[chan struct{}]struct{})
for _, txIn := range tx.MsgTx().TxIn {
prevOut := &txIn.PreviousOutPoint
if cmap, ok := ops[*prevOut]; ok {
if txHex == "" {
txHex = txHexString(tx.MsgTx())
}
marshalledJSON, err := newRedeemingTxNotification(txHex, tx.Index(), block)
if err != nil {
log.Warnf("Failed to marshal redeemingtx notification: %s", err)
continue
}
for wscQuit, wsc := range cmap {
if block != nil {
m.removeSpentRequest(ops, wsc, prevOut)
}
if _, ok := wscNotified[wscQuit]; !ok {
wscNotified[wscQuit] = struct{}{}
wsc.QueueNotification(marshalledJSON)
}
}
}
}
}
// RegisterTxOutAddressRequests requests notifications to the passed websocket
// client when a transaction output spends to the passed address.
func (m *wsNotificationManager) RegisterTxOutAddressRequests(wsc *wsClient, addrs []string) {
m.queueNotification <- &notificationRegisterAddr{
wsc: wsc,
addrs: addrs,
}
}
// addAddrRequests adds the websocket client wsc to the address to client set
// addrMap so wsc will be notified for any mempool or block transaction outputs
// spending to any of the addresses in addrs.
func (*wsNotificationManager) addAddrRequests(addrMap map[string]map[chan struct{}]*wsClient,
wsc *wsClient, addrs []string) {
for _, addr := range addrs {
// Track the request in the client as well so it can be quickly be
// removed on disconnect.
wsc.addrRequests[addr] = struct{}{}
// Add the client to the set of clients to notify when the
// outpoint is seen. Create map as needed.
cmap, ok := addrMap[addr]
if !ok {
cmap = make(map[chan struct{}]*wsClient)
addrMap[addr] = cmap
}
cmap[wsc.quit] = wsc
}
}
// UnregisterTxOutAddressRequest removes a request from the passed websocket
// client to be notified when a transaction spends to the passed address.
func (m *wsNotificationManager) UnregisterTxOutAddressRequest(wsc *wsClient, addr string) {
m.queueNotification <- &notificationUnregisterAddr{
wsc: wsc,
addr: addr,
}
}
// removeAddrRequest removes the websocket client wsc from the address to
// client set addrs so it will no longer receive notification updates for
// any transaction outputs send to addr.
func (*wsNotificationManager) removeAddrRequest(addrs map[string]map[chan struct{}]*wsClient,
wsc *wsClient, addr string) {
// Remove the request tracking from the client.
delete(wsc.addrRequests, addr)
// Remove the client from the list to notify.
cmap, ok := addrs[addr]
if !ok {
log.Warnf("Attempt to remove nonexistent addr request "+
"<%s> for websocket client %s", addr, wsc.addr)
return
}
delete(cmap, wsc.quit)
// Remove the map entry altogether if there are no more clients
// interested in it.
if len(cmap) == 0 {
delete(addrs, addr)
}
}
// AddClient adds the passed websocket client to the notification manager.
func (m *wsNotificationManager) AddClient(wsc *wsClient) {
m.queueNotification <- (*notificationRegisterClient)(wsc)
@ -1213,16 +899,6 @@ type wsClient struct {
// new transaction information from a specific subnetwork.
subnetworkIDForTxUpdates *subnetworkid.SubnetworkID
// addrRequests is a set of addresses the caller has requested to be
// notified about. It is maintained here so all requests can be removed
// when a wallet disconnects. Owned by the notification manager.
addrRequests map[string]struct{}
// spentRequests is a set of unspent Outpoints a wallet has requested
// notifications for when they are spent by a processed transaction.
// Owned by the notification manager.
spentRequests map[wire.OutPoint]struct{}
// filterData is the new generation transaction filter backported from
// github.com/decred/dcrd for the new backported `loadTxFilter` and
// `rescanBlocks` methods.
@ -1659,8 +1335,6 @@ func newWebsocketClient(server *Server, conn *websocket.Conn,
isAdmin: isAdmin,
sessionID: sessionID,
server: server,
addrRequests: make(map[string]struct{}),
spentRequests: make(map[wire.OutPoint]struct{}),
serviceRequestSem: makeSemaphore(config.MainConfig().RPCMaxConcurrentReqs),
ntfnChan: make(chan []byte, 1), // nonblocking sync
sendChan: make(chan wsResponse, websocketSendBufferSize),
@ -1781,23 +1455,6 @@ func handleStopNotifyBlocks(wsc *wsClient, icmd interface{}) (interface{}, error
return nil, nil
}
// handleNotifySpent implements the notifySpent command extension for
// websocket connections.
func handleNotifySpent(wsc *wsClient, icmd interface{}) (interface{}, error) {
cmd, ok := icmd.(*btcjson.NotifySpentCmd)
if !ok {
return nil, btcjson.ErrRPCInternal
}
outpoints, err := deserializeOutpoints(cmd.OutPoints)
if err != nil {
return nil, err
}
wsc.server.ntfnMgr.RegisterSpentRequests(wsc, outpoints)
return nil, nil
}
// handleNotifyNewTransations implements the notifyNewTransactions command
// extension for websocket connections.
func handleNotifyNewTransactions(wsc *wsClient, icmd interface{}) (interface{}, error) {
@ -1862,85 +1519,6 @@ func handleStopNotifyNewTransactions(wsc *wsClient, icmd interface{}) (interface
return nil, nil
}
// handleNotifyReceived implements the notifyReceived command extension for
// websocket connections.
func handleNotifyReceived(wsc *wsClient, icmd interface{}) (interface{}, error) {
cmd, ok := icmd.(*btcjson.NotifyReceivedCmd)
if !ok {
return nil, btcjson.ErrRPCInternal
}
// Decode addresses to validate input, but the strings slice is used
// directly if these are all ok.
err := checkAddressValidity(cmd.Addresses, wsc.server.cfg.DAGParams)
if err != nil {
return nil, err
}
wsc.server.ntfnMgr.RegisterTxOutAddressRequests(wsc, cmd.Addresses)
return nil, nil
}
// handleStopNotifySpent implements the stopNotifySpent command extension for
// websocket connections.
func handleStopNotifySpent(wsc *wsClient, icmd interface{}) (interface{}, error) {
cmd, ok := icmd.(*btcjson.StopNotifySpentCmd)
if !ok {
return nil, btcjson.ErrRPCInternal
}
outpoints, err := deserializeOutpoints(cmd.OutPoints)
if err != nil {
return nil, err
}
for _, outpoint := range outpoints {
wsc.server.ntfnMgr.UnregisterSpentRequest(wsc, outpoint)
}
return nil, nil
}
// handleStopNotifyReceived implements the stopNotifyReceived command extension
// for websocket connections.
func handleStopNotifyReceived(wsc *wsClient, icmd interface{}) (interface{}, error) {
cmd, ok := icmd.(*btcjson.StopNotifyReceivedCmd)
if !ok {
return nil, btcjson.ErrRPCInternal
}
// Decode addresses to validate input, but the strings slice is used
// directly if these are all ok.
err := checkAddressValidity(cmd.Addresses, wsc.server.cfg.DAGParams)
if err != nil {
return nil, err
}
for _, addr := range cmd.Addresses {
wsc.server.ntfnMgr.UnregisterTxOutAddressRequest(wsc, addr)
}
return nil, nil
}
// checkAddressValidity checks the validity of each address in the passed
// string slice. It does this by attempting to decode each address using the
// current active network parameters. If any single address fails to decode
// properly, the function returns an error. Otherwise, nil is returned.
func checkAddressValidity(addrs []string, params *dagconfig.Params) error {
for _, addr := range addrs {
_, err := util.DecodeAddress(addr, params.Prefix)
if err != nil {
return &btcjson.RPCError{
Code: btcjson.ErrRPCInvalidAddressOrKey,
Message: fmt.Sprintf("Invalid address or key: %s",
addr),
}
}
}
return nil
}
// deserializeOutpoints deserializes each serialized outpoint.
func deserializeOutpoints(serializedOuts []btcjson.OutPoint) ([]*wire.OutPoint, error) {
outpoints := make([]*wire.OutPoint, 0, len(serializedOuts))