diff --git a/blockmanager.go b/blockmanager.go index f50cab7b..42531229 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -215,7 +215,6 @@ type blockManager struct { // nolint:maligned // newBlockManager returns a new bitcoin block manager. Use Start to begin // processing asynchronous block and inv updates. func newBlockManager(cfg *blockManagerCfg) (*blockManager, error) { - targetTimespan := int64(cfg.ChainParams.TargetTimespan / time.Second) targetTimePerBlock := int64(cfg.ChainParams.TargetTimePerBlock / time.Second) adjustmentFactor := cfg.ChainParams.RetargetAdjustmentFactor @@ -509,8 +508,8 @@ waitForHeaders: case <-b.quit: b.newHeadersSignal.L.Unlock() return - default: + default: } // Re-acquire the lock in order to check for the filter header @@ -547,7 +546,6 @@ waitForHeaders: // from all peers. We can go on and just request the cfheaders. var goodCheckpoints []*chainhash.Hash for len(goodCheckpoints) == 0 && lastHeight >= wire.CFCheckptInterval { - // Quit if requested. select { case <-b.quit: @@ -1272,10 +1270,10 @@ func (b *blockManager) writeCFHeadersMsg(msg *wire.MsgCFHeaders, // rollBackToHeight rolls back all blocks until it hits the specified height. // It sends notifications along the way. -func (b *blockManager) rollBackToHeight(height uint32) (*headerfs.BlockStamp, error) { +func (b *blockManager) rollBackToHeight(height uint32) error { header, headerHeight, err := b.cfg.BlockHeaders.ChainTip() if err != nil { - return nil, err + return err } bs := &headerfs.BlockStamp{ Height: int32(headerHeight), @@ -1285,13 +1283,13 @@ func (b *blockManager) rollBackToHeight(height uint32) (*headerfs.BlockStamp, er _, regHeight, err := b.cfg.RegFilterHeaders.ChainTip() if err != nil { - return nil, err + return err } for uint32(bs.Height) > height { header, headerHeight, err := b.cfg.BlockHeaders.FetchHeader(&bs.Hash) if err != nil { - return nil, err + return err } newTip := &header.PrevBlock @@ -1300,14 +1298,14 @@ func (b *blockManager) rollBackToHeight(height uint32) (*headerfs.BlockStamp, er if uint32(bs.Height) <= regHeight { newFilterTip, err := b.cfg.RegFilterHeaders.RollbackLastBlock(newTip) if err != nil { - return nil, err + return err } regHeight = uint32(newFilterTip.Height) } bs, err = b.cfg.BlockHeaders.RollbackLastBlock() if err != nil { - return nil, err + return err } // Notifications are asynchronous, so we include the previous @@ -1316,7 +1314,7 @@ func (b *blockManager) rollBackToHeight(height uint32) (*headerfs.BlockStamp, er // can't read it before it's deleted from the store. prevHeader, _, err := b.cfg.BlockHeaders.FetchHeader(newTip) if err != nil { - return nil, err + return err } // Now we send the block disconnected notifications. @@ -1324,7 +1322,8 @@ func (b *blockManager) rollBackToHeight(height uint32) (*headerfs.BlockStamp, er *header, headerHeight, *prevHeader, ) } - return bs, nil + + return nil } // minCheckpointHeight returns the height of the last filter checkpoint for the @@ -1858,6 +1857,7 @@ func (b *blockManager) fetchFilterFromAllPeers( // Ignore this message. if blockHash != response.BlockHash || filterType != response.FilterType { + return } @@ -1903,6 +1903,7 @@ func (b *blockManager) getCheckpts(lastHash *chainhash.Hash, if isCheckpoint { if m.FilterType == fType && m.StopHash == *lastHash { + checkpoints[sp.Addr()] = m.FilterHeaders close(peerQuit) } @@ -2592,7 +2593,7 @@ func (b *blockManager) handleHeadersMsg(hmsg *headersMsg) { b.syncPeerMutex.Lock() b.syncPeer = hmsg.peer b.syncPeerMutex.Unlock() - _, err = b.rollBackToHeight(backHeight) + err = b.rollBackToHeight(backHeight) if err != nil { panic(fmt.Sprintf("Rollback failed: %s", err)) // Should we panic here? @@ -2644,7 +2645,7 @@ func (b *blockManager) handleHeadersMsg(hmsg *headersMsg) { prevCheckpoint.Height, prevCheckpoint.Hash) - _, err := b.rollBackToHeight(uint32( + err := b.rollBackToHeight(uint32( prevCheckpoint.Height), ) if err != nil { @@ -2708,6 +2709,7 @@ func (b *blockManager) handleHeadersMsg(hmsg *headersMsg) { // checkHeaderSanity checks the PoW, and timestamp of a block header. func (b *blockManager) checkHeaderSanity(blockHeader *wire.BlockHeader, maxTimestamp time.Time, reorgAttempt bool) error { + diff, err := b.calcNextRequiredDifficulty( blockHeader.Timestamp, reorgAttempt) if err != nil { @@ -2848,7 +2850,7 @@ func (b *blockManager) findPrevTestNetDifficulty(hList headerlist.Chain) (uint32 iterNode := &startNode.Header iterHeight := startNode.Height for iterNode != nil && iterHeight%b.blocksPerRetarget != 0 && - iterNode.Bits == b.cfg.ChainParams.PowLimitBits { + iterNode.Bits == b.cfg.ChainParams.PowLimitBits { // nolint // Get the previous block node. This function is used over // simply accessing iterNode.parent directly as it will diff --git a/blockmanager_test.go b/blockmanager_test.go index cddb05d4..e3bdc3b4 100644 --- a/blockmanager_test.go +++ b/blockmanager_test.go @@ -238,7 +238,6 @@ func generateResponses(msgs []wire.Message, var prevFilterHeader chainhash.Hash switch q.StartHeight { - // If the start height is 1 the prevFilterHeader is set to the // genesis header. case 1: @@ -426,7 +425,6 @@ func TestBlockManagerInitialInterval(t *testing.T) { "%v", index, testDesc) return } - } errChan <- nil }() @@ -657,7 +655,6 @@ func TestBlockManagerInvalidInterval(t *testing.T) { errChan := make(chan error, 1) go func() { - // Check that the success of the callback match what we // expect. for i := range responses { @@ -726,6 +723,7 @@ func buildNonPushScriptFilter(block *wire.MsgBlock) (*gcs.Filter, error) { // had a push-only script. if txOut.PkScript[0] == txscript.OP_RETURN && txscript.IsPushOnlyScript(txOut.PkScript[1:]) { + continue } diff --git a/headerfs/index.go b/headerfs/index.go index b0b8f4b7..812e4be4 100644 --- a/headerfs/index.go +++ b/headerfs/index.go @@ -94,7 +94,6 @@ func newHeaderIndex(db walletdb.DB, indexType HeaderType) (*headerIndex, error) err := walletdb.Update(db, func(tx walletdb.ReadWriteTx) error { _, err := tx.CreateTopLevelBucket(indexBucket) return err - }) if err != nil && err != walletdb.ErrBucketExists { return nil, err @@ -285,8 +284,8 @@ func (h *headerIndex) chainTipWithTx(tx walletdb.ReadTx) (*chainhash.Hash, // truncateIndex truncates the index for a particular header type by a single // header entry. The passed newTip pointer should point to the hash of the new // chain tip. Optionally, if the entry is to be deleted as well, then the -// delete flag should be set to true. -func (h *headerIndex) truncateIndex(newTip *chainhash.Hash, delete bool) error { +// remove flag should be set to true. +func (h *headerIndex) truncateIndex(newTip *chainhash.Hash, remove bool) error { return walletdb.Update(h.db, func(tx walletdb.ReadWriteTx) error { rootBucket := tx.ReadWriteBucket(indexBucket) @@ -304,10 +303,10 @@ func (h *headerIndex) truncateIndex(newTip *chainhash.Hash, delete bool) error { return fmt.Errorf("unknown index type: %v", h.indexType) } - // If the delete flag is set, then we'll also delete this entry + // If the remove flag is set, then we'll also delete this entry // from the database as the primary index (block headers) is // being rolled back. - if delete { + if remove { prevTipHash := rootBucket.Get(tipKey) err := delHeaderEntry(rootBucket, prevTipHash) if err != nil { diff --git a/headerfs/index_test.go b/headerfs/index_test.go index ad9165e5..6c3a1b77 100644 --- a/headerfs/index_test.go +++ b/headerfs/index_test.go @@ -15,7 +15,7 @@ import ( _ "github.com/btcsuite/btcwallet/walletdb/bdb" ) -func createTestIndex() (func(), *headerIndex, error) { +func createTestIndex(t testing.TB) (func(), *headerIndex, error) { tempDir, err := ioutil.TempDir("", "neutrino") if err != nil { return nil, nil, err @@ -31,7 +31,7 @@ func createTestIndex() (func(), *headerIndex, error) { cleanUp := func() { _ = db.Close() fi, _ := os.Stat(tempDir + "/test.db") - fmt.Printf("DB file size at cleanup: %d bytes\n", fi.Size()) + t.Logf("DB file size at cleanup: %d bytes\n", fi.Size()) _ = os.RemoveAll(tempDir) } @@ -44,7 +44,7 @@ func createTestIndex() (func(), *headerIndex, error) { } func TestAddHeadersIndexRetrieve(t *testing.T) { - cleanUp, hIndex, err := createTestIndex() + cleanUp, hIndex, err := createTestIndex(t) defer cleanUp() if err != nil { t.Fatalf("unable to create test db: %v", err) @@ -115,7 +115,7 @@ func TestAddHeadersIndexRetrieve(t *testing.T) { // location in the bbolt database for reduced memory consumption don't impact // existing users that already have entries in their database. func TestHeaderStorageFallback(t *testing.T) { - cleanUp, hIndex, err := createTestIndex() + cleanUp, hIndex, err := createTestIndex(t) if err != nil { t.Fatalf("unable to create test db: %v", err) } @@ -238,7 +238,7 @@ func BenchmarkWriteHeadersSmallBatch(b *testing.B) { numBatches = 5000 ) for n := 0; n < b.N; n++ { - cleanUp, hIndex, err := createTestIndex() + cleanUp, hIndex, err := createTestIndex(b) if err != nil { b.Fatalf("unable to create test db: %v", err) } @@ -262,7 +262,7 @@ func BenchmarkWriteHeadersMediumBatch(b *testing.B) { numBatches = 250 ) for n := 0; n < b.N; n++ { - cleanUp, hIndex, err := createTestIndex() + cleanUp, hIndex, err := createTestIndex(b) if err != nil { b.Fatalf("unable to create test db: %v", err) } @@ -286,7 +286,7 @@ func BenchmarkWriteHeadersLargeBatch(b *testing.B) { numBatches = 50 ) for n := 0; n < b.N; n++ { - cleanUp, hIndex, err := createTestIndex() + cleanUp, hIndex, err := createTestIndex(b) if err != nil { b.Fatalf("unable to create test db: %v", err) } @@ -306,7 +306,7 @@ func BenchmarkWriteHeadersLargeBatch(b *testing.B) { // index with a hash. func BenchmarkHeightLookupLatency(b *testing.B) { // Start by creating an index with 10k headers. - cleanUp, hIndex, err := createTestIndex() + cleanUp, hIndex, err := createTestIndex(b) if err != nil { b.Fatalf("unable to create test db: %v", err) } diff --git a/headerfs/store.go b/headerfs/store.go index 6fe80f02..a01812a5 100644 --- a/headerfs/store.go +++ b/headerfs/store.go @@ -634,7 +634,6 @@ func NewFilterHeaderStore(filePath string, db walletdb.DB, // If the size of the file is zero, then this means that we haven't yet // written the initial genesis header to disk, so we'll do so now. if fileInfo.Size() == 0 { - var genesisFilterHash chainhash.Hash switch filterType { case RegularFilter: diff --git a/headerfs/store_test.go b/headerfs/store_test.go index 687a165e..3c00736a 100644 --- a/headerfs/store_test.go +++ b/headerfs/store_test.go @@ -20,6 +20,7 @@ import ( func createTestBlockHeaderStore() (func(), walletdb.DB, string, *blockHeaderStore, error) { + tempDir, err := ioutil.TempDir("", "store_test") if err != nil { return nil, nil, "", nil, err diff --git a/headerlist/bounded_header_list_test.go b/headerlist/bounded_header_list_test.go index 1c55864c..1c2165e7 100644 --- a/headerlist/bounded_header_list_test.go +++ b/headerlist/bounded_header_list_test.go @@ -146,7 +146,6 @@ func TestBoundedMemoryChainSizeLimit(t *testing.T) { } } } - } // TestBoundedMemoryChainPrevIteration tests that once we insert elements, we diff --git a/mock_store.go b/mock_store.go index d13e7256..a94a391c 100644 --- a/mock_store.go +++ b/mock_store.go @@ -33,11 +33,12 @@ func newMockBlockHeaderStore() *mockBlockHeaderStore { func (m *mockBlockHeaderStore) ChainTip() (*wire.BlockHeader, uint32, error) { - return nil, 0, nil + return nil, 0, nil } func (m *mockBlockHeaderStore) LatestBlockLocator() ( blockchain.BlockLocator, error) { + return nil, nil } @@ -58,15 +59,16 @@ func (m *mockBlockHeaderStore) FetchHeaderAncestors(uint32, } func (m *mockBlockHeaderStore) HeightFromHash(*chainhash.Hash) (uint32, error) { return 0, nil - } func (m *mockBlockHeaderStore) RollbackLastBlock() (*headerfs.BlockStamp, error) { + return nil, nil } func (m *mockBlockHeaderStore) FetchHeader(h *chainhash.Hash) ( *wire.BlockHeader, uint32, error) { + if header, ok := m.headers[*h]; ok { return &header, 0, nil } diff --git a/neutrino.go b/neutrino.go index 265feccb..1c055977 100644 --- a/neutrino.go +++ b/neutrino.go @@ -365,7 +365,6 @@ func (sp *ServerPeer) OnAddr(_ *peer.Peer, msg *wire.MsgAddr) { } addrsSupportingServices = append(addrsSupportingServices, na) - } // Ignore any addr messages if none of them contained our required @@ -690,6 +689,7 @@ func NewChainService(cfg Config) (*ChainService, error) { // passing a reference to the newly created ChainService. s.queryPeers = func(msg wire.Message, f func(*ServerPeer, wire.Message, chan<- struct{}), qo ...QueryOption) { + queryChainServicePeers(&s, msg, f, qo...) } @@ -755,7 +755,6 @@ func NewChainService(cfg Config) (*ChainService, error) { var newAddressFunc func() (net.Addr, error) if !isDevNetwork(s.chainParams.Net) { newAddressFunc = func() (net.Addr, error) { - // Gather our set of currently connected peers to avoid // connecting to them again. connectedPeers := make(map[string]struct{}) @@ -815,6 +814,7 @@ func NewChainService(cfg Config) (*ChainService, error) { // allow nondefault ports after 50 failed tries. if tries < 50 && fmt.Sprintf("%d", addr.NetAddress().Port) != s.chainParams.DefaultPort { + continue } @@ -969,6 +969,7 @@ func (s *ChainService) GetBlockHash(height int64) (*chainhash.Hash, error) { // error if the hash doesn't exist or is unknown. func (s *ChainService) GetBlockHeader( blockHash *chainhash.Hash) (*wire.BlockHeader, error) { + header, _, err := s.BlockHeaders.FetchHeader(blockHash) return header, err } @@ -1621,12 +1622,14 @@ var _ ChainSource = (*RescanChainSource)(nil) // GetBlockHeaderByHeight returns the header of the block with the given height. func (s *RescanChainSource) GetBlockHeaderByHeight( height uint32) (*wire.BlockHeader, error) { + return s.BlockHeaders.FetchHeaderByHeight(height) } // GetBlockHeader returns the header of the block with the given hash. func (s *RescanChainSource) GetBlockHeader( hash *chainhash.Hash) (*wire.BlockHeader, uint32, error) { + return s.BlockHeaders.FetchHeader(hash) } @@ -1634,6 +1637,7 @@ func (s *RescanChainSource) GetBlockHeader( // height. func (s *RescanChainSource) GetFilterHeaderByHeight( height uint32) (*chainhash.Hash, error) { + return s.RegFilterHeaders.FetchHeaderByHeight(height) } @@ -1643,5 +1647,6 @@ func (s *RescanChainSource) GetFilterHeaderByHeight( // of 0, a backlog will not be delivered. func (s *RescanChainSource) Subscribe( bestHeight uint32) (*blockntfns.Subscription, error) { + return s.blockSubscriptionMgr.NewSubscription(bestHeight) } diff --git a/notifications.go b/notifications.go index 0b59deba..95aac7ab 100644 --- a/notifications.go +++ b/notifications.go @@ -66,7 +66,6 @@ type forAllPeersMsg struct { // goroutines related to peer state. func (s *ChainService) handleQuery(state *peerState, querymsg interface{}) { switch msg := querymsg.(type) { - case getConnCountMsg: nconnected := int32(0) state.forAllPeers(func(sp *ServerPeer) { diff --git a/pushtx/broadcaster.go b/pushtx/broadcaster.go index 9576175e..f1f26ce5 100644 --- a/pushtx/broadcaster.go +++ b/pushtx/broadcaster.go @@ -161,7 +161,6 @@ func (b *Broadcaster) broadcastHandler(sub *blockntfns.Subscription) { b.rebroadcast(txs, b.confChan) rebroadcastSem <- struct{}{} }() - } reBroadcastTicker := time.NewTicker(b.cfg.RebroadcastInterval) diff --git a/query.go b/query.go index 41d886b4..4e829aff 100644 --- a/query.go +++ b/query.go @@ -627,7 +627,6 @@ func (s *ChainService) prepareCFiltersQuery(blockHash chainhash.Hash, } switch qo.optimisticBatch { - // No batching, the start and stop height will be the same. case noBatch: startHeight = int64(height) @@ -931,7 +930,6 @@ func (s *ChainService) GetCFilter(blockHash chainhash.Hash, // filter to the caller. for { select { - case filter, ok = <-query.filterChan: if !ok { // Query has finished, if we have a result we'll @@ -1005,8 +1003,7 @@ func (s *ChainService) GetBlock(blockHash chainhash.Hash, // Check responses and if we get one that matches, end the // query early. - func(sp *ServerPeer, resp wire.Message, - quit chan<- struct{}) { + func(sp *ServerPeer, resp wire.Message, quit chan<- struct{}) { switch response := resp.(type) { // We're only interested in "block" messages. case *wire.MsgBlock: diff --git a/query/interface.go b/query/interface.go index a1c7fa6b..0fbffeae 100644 --- a/query/interface.go +++ b/query/interface.go @@ -36,7 +36,7 @@ type queryOptions struct { // methods, such as GetBlock and GetCFilter (when that resorts to a network // query). These are always processed in order, with later options overriding // earlier ones. -type QueryOption func(*queryOptions) // nolint:golint +type QueryOption func(*queryOptions) // nolint // defaultQueryOptions returns a queryOptions set to package-level defaults. func defaultQueryOptions() *queryOptions { diff --git a/query/workmanager.go b/query/workmanager.go index 76e801a1..dc2e9399 100644 --- a/query/workmanager.go +++ b/query/workmanager.go @@ -253,7 +253,6 @@ Loop: // previous query to come back, a new peer to connect, or for a // new batch of queries to be scheduled. select { - // Spin up a goroutine that runs a worker each time a peer // connects. case peer := <-peersConnected: @@ -315,7 +314,6 @@ Loop: if batch != nil { batch.errChan <- result.err delete(currentBatches, batchNum) - batch = nil log.Debugf("Canceled batch %v", batchNum) @@ -364,7 +362,6 @@ Loop: if batch.rem == 0 { batch.errChan <- nil delete(currentBatches, batchNum) - batch = nil log.Tracef("Batch %v done", batchNum) @@ -380,7 +377,6 @@ Loop: case <-batch.timeout: batch.errChan <- ErrQueryTimeout delete(currentBatches, batchNum) - batch = nil log.Warnf("Query(%d) failed with "+ "error: %v. Timing out.", diff --git a/query/workmanager_test.go b/query/workmanager_test.go index b9609121..fdb00c84 100644 --- a/query/workmanager_test.go +++ b/query/workmanager_test.go @@ -365,7 +365,6 @@ func TestWorkManagerCancelBatch(t *testing.T) { case <-time.After(time.Second): t.Fatalf("result not handled") } - } // The query should exit with an error. @@ -422,6 +421,7 @@ func TestWorkManagerWorkRankingScheduling(t *testing.T) { even := func(p string) bool { if p == "mock0" || p == "mock2" || p == "mock4" || p == "mock6" { + return true } return false @@ -436,7 +436,6 @@ func TestWorkManagerWorkRankingScheduling(t *testing.T) { } return i < j - } // Go backwards, and succeed the queries. for i := numQueries - 1; i >= 0; i-- { diff --git a/query_test.go b/query_test.go index 37793e64..345ec1b6 100644 --- a/query_test.go +++ b/query_test.go @@ -127,6 +127,7 @@ func genRandomBlockHash() *chainhash.Hash { // originally taken from filterdb/db_test.go. func genRandFilter(numElements uint32, t *testing.T) ( *chainhash.Hash, *gcs.Filter, uint64) { + elements := make([][]byte, numElements) for i := uint32(0); i < numElements; i++ { var elem [20]byte @@ -308,7 +309,6 @@ func TestBlockCache(t *testing.T) { // Serve the block that matches the requested block header. for _, b := range blocks { if *b.Hash() == inv.Hash { - // Execute the callback with the found block, // and wait for the quit channel to be closed. quit := make(chan struct{}) diff --git a/rescan.go b/rescan.go index 5a46117d..8b68bfda 100644 --- a/rescan.go +++ b/rescan.go @@ -654,6 +654,7 @@ rescanLoop: if curStamp.Hash == ro.endBlock.Hash || (ro.endBlock.Height > 0 && curStamp.Height == ro.endBlock.Height) { + return nil } @@ -667,7 +668,6 @@ rescanLoop: // alternatively, forward ourselves to the next block // if possible. select { - case <-ro.quit: return ErrRescanExit @@ -1158,13 +1158,18 @@ func (ro *rescanOptions) updateFilter(chain ChainSource, update *updateOptions, for curStamp.Height > int32(update.rewind) { if ro.ntfn.OnBlockDisconnected != nil && // nolint:staticcheck !update.disableDisconnectedNtfns { - ro.ntfn.OnBlockDisconnected(&curStamp.Hash, // nolint:staticcheck - curStamp.Height, curHeader.Timestamp) + + ro.ntfn.OnBlockDisconnected( // nolint:staticcheck + &curStamp.Hash, + curStamp.Height, curHeader.Timestamp, + ) } if ro.ntfn.OnFilteredBlockDisconnected != nil && !update.disableDisconnectedNtfns { - ro.ntfn.OnFilteredBlockDisconnected(curStamp.Height, - curHeader) + + ro.ntfn.OnFilteredBlockDisconnected( + curStamp.Height, curHeader, + ) } // We just disconnected a block above, so we're now in rewind @@ -1317,7 +1322,7 @@ func (r *Rescan) Start() <-chan error { go func() { defer r.wg.Done() - rescanArgs := append(r.options, updateChan(r.updateChan)) + rescanArgs := append(r.options, updateChan(r.updateChan)) // nolint err := rescan(r.chain, rescanArgs...) close(r.running) diff --git a/rescan_test.go b/rescan_test.go index 87d26bac..e611eb90 100644 --- a/rescan_test.go +++ b/rescan_test.go @@ -171,9 +171,7 @@ func (c *mockChainSource) rollback(notify bool) headerfs.BlockStamp { // rollbackToHeight rolls back the chain to the specified height. The notify // boolean can be used to notify all stale blocks. -func (c *mockChainSource) rollbackToHeight(height int32, - notify bool) headerfs.BlockStamp { - +func (c *mockChainSource) rollbackToHeight(height int32, notify bool) { c.mu.Lock() bestBlock := c.bestBlock c.mu.Unlock() @@ -181,8 +179,6 @@ func (c *mockChainSource) rollbackToHeight(height int32, for bestBlock.Height > height { bestBlock = c.rollback(notify) } - - return bestBlock } // ChainParams returns the parameters of the current chain. diff --git a/sync_test.go b/sync_test.go index 10142d23..a59ca950 100644 --- a/sync_test.go +++ b/sync_test.go @@ -61,7 +61,7 @@ var ( // "rv": OnRecvTx // "rd": OnRedeemingTx // "bd": OnBlockDisconnected - // "fd": OnFilteredBlockDisconnected + // "fd": OnFilteredBlockDisconnected. wantLog = func() (log []byte) { for i := 1096; i <= 1100; i++ { // FilteredBlockConnected @@ -222,6 +222,7 @@ func (s *secSource) add(privKey *btcec.PrivateKey) (btcutil.Address, error) { // GetKey is required by the txscript.KeyDB interface. func (s *secSource) GetKey(addr btcutil.Address) (*btcec.PrivateKey, bool, error) { + privKey, ok := s.keys[addr.String()] if !ok { return nil, true, fmt.Errorf("No key for address %s", addr) @@ -238,7 +239,7 @@ func (s *secSource) GetScript(addr btcutil.Address) ([]byte, error) { return *script, nil } -// ChainParams is required by the SecretsSource interface +// ChainParams is required by the SecretsSource interface. func (s *secSource) ChainParams() *chaincfg.Params { return s.params } @@ -442,16 +443,19 @@ func testStartRescan(harness *neutrinoHarness, t *testing.T) { inSrc := func(tx wire.MsgTx) func(target btcutil.Amount) ( total btcutil.Amount, inputs []*wire.TxIn, inputValues []btcutil.Amount, scripts [][]byte, err error) { + ourIndex := 1 << 30 // Should work on 32-bit systems for i, txo := range tx.TxOut { if bytes.Equal(txo.PkScript, script1) || bytes.Equal(txo.PkScript, script2) { + ourIndex = i } } return func(target btcutil.Amount) (total btcutil.Amount, inputs []*wire.TxIn, inputValues []btcutil.Amount, scripts [][]byte, err error) { + if ourIndex == 1<<30 { err = fmt.Errorf("Couldn't find our address " + "in the passed transaction's outputs.") @@ -878,8 +882,10 @@ func testRandomBlocks(harness *neutrinoHarness, t *testing.T) { return } // Check that network and RPC blocks match. - if !reflect.DeepEqual(*haveBlock.MsgBlock(), - *wantBlock) { + if !reflect.DeepEqual( + *haveBlock.MsgBlock(), *wantBlock, + ) { + errChan <- fmt.Errorf("Block from network "+ "doesn't match block from RPC. Want: "+ "%s, RPC: %s, network: %s", blockHash, @@ -1210,6 +1216,7 @@ func checkErrChan(t *testing.T, errChan <-chan error) { // waitForSync waits for the ChainService to sync to the current chain state. func waitForSync(t *testing.T, svc *neutrino.ChainService, correctSyncNode *rpctest.Harness) error { + knownBestHash, knownBestHeight, err := correctSyncNode.Client.GetBestBlock() if err != nil { @@ -1379,6 +1386,7 @@ func waitForSync(t *testing.T, svc *neutrino.ChainService, func startRescan(t *testing.T, svc *neutrino.ChainService, addr btcutil.Address, startBlock *headerfs.BlockStamp, quit <-chan struct{}) ( *neutrino.Rescan, <-chan error) { + rescan := neutrino.NewRescan( &neutrino.RescanChainSource{svc}, neutrino.QuitChan(quit), @@ -1389,6 +1397,7 @@ func startRescan(t *testing.T, svc *neutrino.ChainService, addr btcutil.Address, OnBlockConnected: func( hash *chainhash.Hash, height int32, time time.Time) { + rescanMtx.Lock() gotLog = append(gotLog, []byte("bc")...) @@ -1398,6 +1407,7 @@ func startRescan(t *testing.T, svc *neutrino.ChainService, addr btcutil.Address, OnBlockDisconnected: func( hash *chainhash.Hash, height int32, time time.Time) { + rescanMtx.Lock() delete(ourKnownTxsByBlock, *hash) gotLog = append(gotLog, @@ -1407,6 +1417,7 @@ func startRescan(t *testing.T, svc *neutrino.ChainService, addr btcutil.Address, }, OnRecvTx: func(tx *btcutil.Tx, details *btcjson.BlockDetails) { + rescanMtx.Lock() hash, err := chainhash. NewHashFromStr( @@ -1427,6 +1438,7 @@ func startRescan(t *testing.T, svc *neutrino.ChainService, addr btcutil.Address, }, OnRedeemingTx: func(tx *btcutil.Tx, details *btcjson.BlockDetails) { + rescanMtx.Lock() hash, err := chainhash. NewHashFromStr( @@ -1449,6 +1461,7 @@ func startRescan(t *testing.T, svc *neutrino.ChainService, addr btcutil.Address, height int32, header *wire.BlockHeader, relevantTxs []*btcutil.Tx) { + rescanMtx.Lock() ourKnownTxsByFilteredBlock[header.BlockHash()] = relevantTxs @@ -1462,6 +1475,7 @@ func startRescan(t *testing.T, svc *neutrino.ChainService, addr btcutil.Address, OnFilteredBlockDisconnected: func( height int32, header *wire.BlockHeader) { + rescanMtx.Lock() delete(ourKnownTxsByFilteredBlock, header.BlockHash()) diff --git a/utxoscanner_test.go b/utxoscanner_test.go index 5dbd1100..efbab25a 100644 --- a/utxoscanner_test.go +++ b/utxoscanner_test.go @@ -36,6 +36,7 @@ func (c *MockChainClient) SetBlock(hash *chainhash.Hash, block *btcutil.Block) { func (c *MockChainClient) GetBlockFromNetwork(blockHash chainhash.Hash, options ...QueryOption) (*btcutil.Block, error) { + return c.getBlockResponse[blockHash], nil } @@ -61,6 +62,7 @@ func (c *MockChainClient) BestSnapshot() (*headerfs.BlockStamp, error) { func (c *MockChainClient) blockFilterMatches(ro *rescanOptions, blockHash *chainhash.Hash) (bool, error) { + return true, nil } @@ -75,7 +77,6 @@ func makeTestInputWithScript() *InputWithScript { }, PkScript: pkScript, } - } // TestFindSpends tests that findSpends properly returns spend reports. @@ -474,8 +475,9 @@ func TestUtxoScannerCancelRequest(t *testing.T) { // finally returns. block := make(chan struct{}) scanner := NewUtxoScanner(&UtxoScannerConfig{ - GetBlock: func(chainhash.Hash, ...QueryOption, - ) (*btcutil.Block, error) { + GetBlock: func(chainhash.Hash, + ...QueryOption) (*btcutil.Block, error) { + <-block return nil, fetchErr },