Skip to content

Commit

Permalink
Use same notification for mined transactions and blocks. (btcsuite#434)
Browse files Browse the repository at this point in the history
Change the block connected and disconnected notifications to include
the entire block header.

Do not notify the previous block's regular tree transactions if the
newly attached block voted to approve them.  Instead, notify the
regular transactions from the newly attached block.  It is up to the
client to check the vote bits in the header to decide how to handle
the previous block's regular transactions.

Every websocket client now has an associated transaction filter that
is used to determine whether or not a processed transaction is (or
might be) relevant to the client.  A new RPC, loadtxfilter, has been
added to load, reload, or add to this filter.

Redo the entire rescan RPC to scan over previously-processed blocks
using the same transaction filter (rather than specifying which
addresses and outpoints to watch for in the rescan request).

Fixes btcsuite#433.
  • Loading branch information
jrick authored Nov 8, 2016
1 parent 2d242b2 commit ed7c45a
Show file tree
Hide file tree
Showing 9 changed files with 588 additions and 1,597 deletions.
110 changes: 32 additions & 78 deletions dcrjson/chainsvrwscmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,32 @@ func NewAuthenticateCmd(username, passphrase string) *AuthenticateCmd {
}
}

// OutPoint describes a transaction outpoint that will be marshalled to and
// from JSON. Contains Decred addition.
type OutPoint struct {
Hash string `json:"hash"`
Tree int8 `json:"tree"`
Index uint32 `json:"index"`
}

// LoadTxFilterCmd defines the loadtxfilter request parameters to load or
// reload a transaction filter.
type LoadTxFilterCmd struct {
Reload bool
Addresses []string
OutPoints []OutPoint
}

// NewLoadTxFilterCmd returns a new instance which can be used to issue a
// loadtxfilter JSON-RPC command.
func NewLoadTxFilterCmd(reload bool, addresses []string, outPoints []OutPoint) *LoadTxFilterCmd {
return &LoadTxFilterCmd{
Reload: reload,
Addresses: addresses,
OutPoints: outPoints,
}
}

// NotifyBlocksCmd defines the notifyblocks JSON-RPC command.
type NotifyBlocksCmd struct{}

Expand Down Expand Up @@ -78,101 +104,29 @@ func NewStopNotifyNewTransactionsCmd() *StopNotifyNewTransactionsCmd {
return &StopNotifyNewTransactionsCmd{}
}

// NotifyReceivedCmd defines the notifyreceived JSON-RPC command.
type NotifyReceivedCmd struct {
Addresses []string
}

// NewNotifyReceivedCmd returns a new instance which can be used to issue a
// notifyreceived JSON-RPC command.
func NewNotifyReceivedCmd(addresses []string) *NotifyReceivedCmd {
return &NotifyReceivedCmd{
Addresses: addresses,
}
}

// OutPoint describes a transaction outpoint that will be marshalled to and
// from JSON. Contains Decred addition.
type OutPoint struct {
Hash string `json:"hash"`
Tree int8 `json:"tree"`
Index uint32 `json:"index"`
}

// NotifySpentCmd defines the notifyspent JSON-RPC command.
type NotifySpentCmd struct {
OutPoints []OutPoint
}

// NewNotifySpentCmd returns a new instance which can be used to issue a
// notifyspent JSON-RPC command.
func NewNotifySpentCmd(outPoints []OutPoint) *NotifySpentCmd {
return &NotifySpentCmd{
OutPoints: outPoints,
}
}

// StopNotifyReceivedCmd defines the stopnotifyreceived JSON-RPC command.
type StopNotifyReceivedCmd struct {
Addresses []string
}

// NewStopNotifyReceivedCmd returns a new instance which can be used to issue a
// stopnotifyreceived JSON-RPC command.
func NewStopNotifyReceivedCmd(addresses []string) *StopNotifyReceivedCmd {
return &StopNotifyReceivedCmd{
Addresses: addresses,
}
}

// StopNotifySpentCmd defines the stopnotifyspent JSON-RPC command.
type StopNotifySpentCmd struct {
OutPoints []OutPoint
}

// NewStopNotifySpentCmd returns a new instance which can be used to issue a
// stopnotifyspent JSON-RPC command.
func NewStopNotifySpentCmd(outPoints []OutPoint) *StopNotifySpentCmd {
return &StopNotifySpentCmd{
OutPoints: outPoints,
}
}

// RescanCmd defines the rescan JSON-RPC command.
type RescanCmd struct {
BeginBlock string
Addresses []string
OutPoints []OutPoint
EndBlock *string
// Concatinated block hashes in non-byte-reversed hex encoding. Must
// have length evenly divisible by 2*chainhash.HashSize.
BlockHashes string
}

// NewRescanCmd returns a new instance which can be used to issue a rescan
// JSON-RPC command.
//
// The parameters which are pointers indicate they are optional. Passing nil
// for optional parameters will use the default value.
func NewRescanCmd(beginBlock string, addresses []string, outPoints []OutPoint, endBlock *string) *RescanCmd {
return &RescanCmd{
BeginBlock: beginBlock,
Addresses: addresses,
OutPoints: outPoints,
EndBlock: endBlock,
}
func NewRescanCmd(blockHashes string) *RescanCmd {
return &RescanCmd{BlockHashes: blockHashes}
}

func init() {
// The commands in this file are only usable by websockets.
flags := UFWebsocketOnly

MustRegisterCmd("authenticate", (*AuthenticateCmd)(nil), flags)
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("rescan", (*RescanCmd)(nil), flags)
}
88 changes: 4 additions & 84 deletions dcrjson/chainsvrwscmds_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,97 +100,17 @@ func TestChainSvrWsCmds(t *testing.T) {
marshalled: `{"jsonrpc":"1.0","method":"stopnotifynewtransactions","params":[],"id":1}`,
unmarshalled: &dcrjson.StopNotifyNewTransactionsCmd{},
},
{
name: "notifyreceived",
newCmd: func() (interface{}, error) {
return dcrjson.NewCmd("notifyreceived", []string{"1Address"})
},
staticCmd: func() interface{} {
return dcrjson.NewNotifyReceivedCmd([]string{"1Address"})
},
marshalled: `{"jsonrpc":"1.0","method":"notifyreceived","params":[["1Address"]],"id":1}`,
unmarshalled: &dcrjson.NotifyReceivedCmd{
Addresses: []string{"1Address"},
},
},
{
name: "stopnotifyreceived",
newCmd: func() (interface{}, error) {
return dcrjson.NewCmd("stopnotifyreceived", []string{"1Address"})
},
staticCmd: func() interface{} {
return dcrjson.NewStopNotifyReceivedCmd([]string{"1Address"})
},
marshalled: `{"jsonrpc":"1.0","method":"stopnotifyreceived","params":[["1Address"]],"id":1}`,
unmarshalled: &dcrjson.StopNotifyReceivedCmd{
Addresses: []string{"1Address"},
},
},
{
name: "notifyspent",
newCmd: func() (interface{}, error) {
return dcrjson.NewCmd("notifyspent", `[{"hash":"123","index":0}]`)
},
staticCmd: func() interface{} {
ops := []dcrjson.OutPoint{{Hash: "123", Index: 0}}
return dcrjson.NewNotifySpentCmd(ops)
},
marshalled: `{"jsonrpc":"1.0","method":"notifyspent","params":[[{"hash":"123","tree":0,"index":0}]],"id":1}`,
unmarshalled: &dcrjson.NotifySpentCmd{
OutPoints: []dcrjson.OutPoint{{Hash: "123", Index: 0}},
},
},
{
name: "stopnotifyspent",
newCmd: func() (interface{}, error) {
return dcrjson.NewCmd("stopnotifyspent", `[{"hash":"123","index":0}]`)
},
staticCmd: func() interface{} {
ops := []dcrjson.OutPoint{{Hash: "123", Index: 0}}
return dcrjson.NewStopNotifySpentCmd(ops)
},
marshalled: `{"jsonrpc":"1.0","method":"stopnotifyspent","params":[[{"hash":"123","tree":0,"index":0}]],"id":1}`,
unmarshalled: &dcrjson.StopNotifySpentCmd{
OutPoints: []dcrjson.OutPoint{{Hash: "123", Index: 0}},
},
},
{
name: "rescan",
newCmd: func() (interface{}, error) {
return dcrjson.NewCmd("rescan", "123", `["1Address"]`, `[{"hash":"0000000000000000000000000000000000000000000000000000000000000123","tree":0,"index":0}]`)
},
staticCmd: func() interface{} {
addrs := []string{"1Address"}
ops := []dcrjson.OutPoint{{
Hash: "0000000000000000000000000000000000000000000000000000000000000123",
Index: 0,
}}
return dcrjson.NewRescanCmd("123", addrs, ops, nil)
},
marshalled: `{"jsonrpc":"1.0","method":"rescan","params":["123",["1Address"],[{"hash":"0000000000000000000000000000000000000000000000000000000000000123","tree":0,"index":0}]],"id":1}`,
unmarshalled: &dcrjson.RescanCmd{
BeginBlock: "123",
Addresses: []string{"1Address"},
OutPoints: []dcrjson.OutPoint{{Hash: "0000000000000000000000000000000000000000000000000000000000000123", Index: 0}},
EndBlock: nil,
},
},
{
name: "rescan optional",
newCmd: func() (interface{}, error) {
return dcrjson.NewCmd("rescan", "123", `["1Address"]`, `[{"hash":"123","tree":0,"index":0}]`, "456")
return dcrjson.NewCmd("rescan", "0000000000000000000000000000000000000000000000000000000000000123")
},
staticCmd: func() interface{} {
addrs := []string{"1Address"}
ops := []dcrjson.OutPoint{{Hash: "123", Index: 0}}
return dcrjson.NewRescanCmd("123", addrs, ops, dcrjson.String("456"))
return dcrjson.NewRescanCmd("0000000000000000000000000000000000000000000000000000000000000123")
},
marshalled: `{"jsonrpc":"1.0","method":"rescan","params":["123",["1Address"],[{"hash":"123","tree":0,"index":0}],"456"],"id":1}`,
marshalled: `{"jsonrpc":"1.0","method":"rescan","params":["0000000000000000000000000000000000000000000000000000000000000123"],"id":1}`,
unmarshalled: &dcrjson.RescanCmd{
BeginBlock: "123",
Addresses: []string{"1Address"},
OutPoints: []dcrjson.OutPoint{{Hash: "123", Index: 0}},
EndBlock: dcrjson.String("456"),
BlockHashes: "0000000000000000000000000000000000000000000000000000000000000123",
},
},
}
Expand Down
Loading

0 comments on commit ed7c45a

Please sign in to comment.