rpctest: Update to use new filtered block ntfns.

This modifies the rpctest harness and its associated memwallet to make
use of the new filter-based notifications since the old notifications
are now deprecated.

It also updates the glide.lock file to require the necessary
btcrpcclient version.
This commit is contained in:
Dave Collins 2017-01-27 19:54:25 -06:00
parent 6a54323258
commit 554460feda
No known key found for this signature in database
GPG key ID: B8904D9D9C93D1F2
3 changed files with 47 additions and 39 deletions

4
glide.lock generated
View file

@ -1,10 +1,10 @@
hash: ea6e6ffa31517aacb35de06b097975229096253bf658d302f2d6652fde91b3f1 hash: ea6e6ffa31517aacb35de06b097975229096253bf658d302f2d6652fde91b3f1
updated: 2017-01-11T15:54:00.925235328-05:00 updated: 2017-01-27T20:06:58.5779336-06:00
imports: imports:
- name: github.com/btcsuite/btclog - name: github.com/btcsuite/btclog
version: 73889fb79bd687870312b6e40effcecffbd57d30 version: 73889fb79bd687870312b6e40effcecffbd57d30
- name: github.com/btcsuite/btcrpcclient - name: github.com/btcsuite/btcrpcclient
version: 5ce0ed600997eafaed25ad4936c1d84ec6ad2b5a version: abcdfb702a7ca67e4a32c10be380c63216bd69fe
- name: github.com/btcsuite/btcutil - name: github.com/btcsuite/btcutil
version: 86346b5a958c0cf94186b87855469ae991be501c version: 86346b5a958c0cf94186b87855469ae991be501c
subpackages: subpackages:

View file

@ -1,4 +1,4 @@
// Copyright (c) 2016 The btcsuite developers // Copyright (c) 2016-2017 The btcsuite developers
// Use of this source code is governed by an ISC // Use of this source code is governed by an ISC
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
@ -9,7 +9,6 @@ import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"sync" "sync"
"time"
"github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/blockchain"
"github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/btcec"
@ -55,8 +54,8 @@ func (u *utxo) isMature(height int32) bool {
// used to sync up the memWallet each time a new block is connected to the main // used to sync up the memWallet each time a new block is connected to the main
// chain. // chain.
type chainUpdate struct { type chainUpdate struct {
blockHash *chainhash.Hash blockHeight int32
blockHeight int32 filteredTxns []*btcutil.Tx
} }
// undoEntry is functionally the opposite of a chainUpdate. An undoEntry is // undoEntry is functionally the opposite of a chainUpdate. An undoEntry is
@ -179,11 +178,11 @@ func (m *memWallet) SetRPCClient(rpcClient *btcrpcclient.Client) {
// IngestBlock is a call-back which is to be triggered each time a new block is // IngestBlock is a call-back which is to be triggered each time a new block is
// connected to the main chain. Ingesting a block updates the wallet's internal // connected to the main chain. Ingesting a block updates the wallet's internal
// utxo state based on the outputs created and destroyed within each block. // utxo state based on the outputs created and destroyed within each block.
func (m *memWallet) IngestBlock(blockHash *chainhash.Hash, height int32, t time.Time) { func (m *memWallet) IngestBlock(height int32, header *wire.BlockHeader, filteredTxns []*btcutil.Tx) {
// Append this new chain update to the end of the queue of new chain // Append this new chain update to the end of the queue of new chain
// updates. // updates.
m.chainMtx.Lock() m.chainMtx.Lock()
m.chainUpdates = append(m.chainUpdates, &chainUpdate{blockHash, height}) m.chainUpdates = append(m.chainUpdates, &chainUpdate{height, filteredTxns})
m.chainMtx.Unlock() m.chainMtx.Unlock()
// Launch a goroutine to signal the chainSyncer that a new update is // Launch a goroutine to signal the chainSyncer that a new update is
@ -210,21 +209,16 @@ func (m *memWallet) chainSyncer() {
m.chainUpdates = m.chainUpdates[1:] m.chainUpdates = m.chainUpdates[1:]
m.chainMtx.Unlock() m.chainMtx.Unlock()
// Fetch the new block so we can process it shortly below. // Update the latest synced height, then process each filtered
block, err := m.rpc.GetBlock(update.blockHash) // transaction in the block creating and destroying utxos within
if err != nil { // the wallet as a result.
return
}
// Update the latest synced height, then process each
// transaction in the block creating and destroying utxos
// within the wallet as a result.
m.Lock() m.Lock()
m.currentHeight = update.blockHeight m.currentHeight = update.blockHeight
undo := &undoEntry{ undo := &undoEntry{
utxosDestroyed: make(map[wire.OutPoint]*utxo), utxosDestroyed: make(map[wire.OutPoint]*utxo),
} }
for _, mtx := range block.Transactions { for _, tx := range update.filteredTxns {
mtx := tx.MsgTx()
isCoinbase := blockchain.IsCoinBaseTx(mtx) isCoinbase := blockchain.IsCoinBaseTx(mtx)
txHash := mtx.TxHash() txHash := mtx.TxHash()
m.evalOutputs(mtx.TxOut, &txHash, isCoinbase, undo) m.evalOutputs(mtx.TxOut, &txHash, isCoinbase, undo)
@ -293,7 +287,7 @@ func (m *memWallet) evalInputs(inputs []*wire.TxIn, undo *undoEntry) {
// UnwindBlock is a call-back which is to be executed each time a block is // UnwindBlock is a call-back which is to be executed each time a block is
// disconnected from the main chain. Unwinding a block undoes the effect that a // disconnected from the main chain. Unwinding a block undoes the effect that a
// particular block had on the wallet's internal utxo state. // particular block had on the wallet's internal utxo state.
func (m *memWallet) UnwindBlock(hash *chainhash.Hash, height int32, t time.Time) { func (m *memWallet) UnwindBlock(height int32, header *wire.BlockHeader) {
m.Lock() m.Lock()
defer m.Unlock() defer m.Unlock()
@ -310,7 +304,9 @@ func (m *memWallet) UnwindBlock(hash *chainhash.Hash, height int32, t time.Time)
delete(m.reorgJournal, height) delete(m.reorgJournal, height)
} }
// newAddress returns a new address from the wallet's hd key chain. // newAddress returns a new address from the wallet's hd key chain. It also
// loads the address into the RPC client's transaction filter to ensure any
// transactions that involve it are delivered via the notifications.
func (m *memWallet) newAddress() (btcutil.Address, error) { func (m *memWallet) newAddress() (btcutil.Address, error) {
index := m.hdIndex index := m.hdIndex
@ -328,6 +324,11 @@ func (m *memWallet) newAddress() (btcutil.Address, error) {
return nil, err return nil, err
} }
err = m.rpc.LoadTxFilter(false, []btcutil.Address{addr}, nil)
if err != nil {
return nil, err
}
m.addrs[index] = addr m.addrs[index] = addr
m.hdIndex++ m.hdIndex++

View file

@ -1,4 +1,4 @@
// Copyright (c) 2016 The btcsuite developers // Copyright (c) 2016-2017 The btcsuite developers
// Use of this source code is governed by an ISC // Use of this source code is governed by an ISC
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
@ -160,28 +160,28 @@ func New(activeNet *chaincfg.Params, handlers *btcrpcclient.NotificationHandlers
handlers = &btcrpcclient.NotificationHandlers{} handlers = &btcrpcclient.NotificationHandlers{}
} }
// If a handler for the OnBlockConnected/OnBlockDisconnected callback // If a handler for the OnFilteredBlock{Connected,Disconnected} callback
// has already been set, then we create a wrapper callback which // callback has already been set, then create a wrapper callback which
// executes both the currently registered callback, and the mem // executes both the currently registered callback and the mem wallet's
// wallet's callback. // callback.
if handlers.OnBlockConnected != nil { if handlers.OnFilteredBlockConnected != nil {
obc := handlers.OnBlockConnected obc := handlers.OnFilteredBlockConnected
handlers.OnBlockConnected = func(hash *chainhash.Hash, height int32, t time.Time) { handlers.OnFilteredBlockConnected = func(height int32, header *wire.BlockHeader, filteredTxns []*btcutil.Tx) {
wallet.IngestBlock(hash, height, t) wallet.IngestBlock(height, header, filteredTxns)
obc(hash, height, t) obc(height, header, filteredTxns)
} }
} else { } else {
// Otherwise, we can claim the callback ourselves. // Otherwise, we can claim the callback ourselves.
handlers.OnBlockConnected = wallet.IngestBlock handlers.OnFilteredBlockConnected = wallet.IngestBlock
} }
if handlers.OnBlockDisconnected != nil { if handlers.OnFilteredBlockDisconnected != nil {
obd := handlers.OnBlockConnected obd := handlers.OnFilteredBlockDisconnected
handlers.OnBlockDisconnected = func(hash *chainhash.Hash, height int32, t time.Time) { handlers.OnFilteredBlockDisconnected = func(height int32, header *wire.BlockHeader) {
wallet.UnwindBlock(hash, height, t) wallet.UnwindBlock(height, header)
obd(hash, height, t) obd(height, header)
} }
} else { } else {
handlers.OnBlockDisconnected = wallet.UnwindBlock handlers.OnFilteredBlockDisconnected = wallet.UnwindBlock
} }
h := &Harness{ h := &Harness{
@ -220,8 +220,15 @@ func (h *Harness) SetUp(createTestChain bool, numMatureOutputs uint32) error {
h.wallet.Start() h.wallet.Start()
// Ensure the btcd properly dispatches our registered call-back for // Filter transactions that pay to the coinbase associated with the
// each new block. Otherwise, the memWallet won't function properly. // wallet.
filterAddrs := []btcutil.Address{h.wallet.coinbaseAddr}
if err := h.Node.LoadTxFilter(true, filterAddrs, nil); err != nil {
return err
}
// Ensure btcd properly dispatches our registered call-back for each new
// block. Otherwise, the memWallet won't function properly.
if err := h.Node.NotifyBlocks(); err != nil { if err := h.Node.NotifyBlocks(); err != nil {
return err return err
} }