Example #1
0
// handleChainNotifications is the major chain notification handler that
// receives websocket notifications about the blockchain.
func (w *Wallet) handleChainNotifications() {
	chainClient, err := w.requireChainClient()
	if err != nil {
		log.Errorf("handleChainNotifications called without RPC client")
		w.wg.Done()
		return
	}

	// At the moment there is no recourse if the rescan fails for
	// some reason, however, the wallet will not be marked synced
	// and many methods will error early since the wallet is known
	// to be out of date.
	err = w.syncWithChain()
	if err != nil && !w.ShuttingDown() {
		log.Warnf("Unable to synchronize wallet to chain: %v", err)
	}

	for n := range chainClient.Notifications() {
		var err error
		strErrType := ""

		switch n := n.(type) {
		case chain.ClientConnected:
			log.Infof("The client has successfully connected to dcrd and " +
				"is now handling websocket notifications")
		case chain.BlockConnected:
			err = walletdb.Update(w.db, func(tx walletdb.ReadWriteTx) error {
				return w.connectBlock(tx, wtxmgr.BlockMeta(n))
			})
			strErrType = "BlockConnected"
		case chain.BlockDisconnected:
			err = walletdb.Update(w.db, func(tx walletdb.ReadWriteTx) error {
				return w.disconnectBlock(tx, wtxmgr.BlockMeta(n))
			})
			strErrType = "BlockDisconnected"
		case chain.Reorganization:
			w.handleReorganizing(n.OldHash, n.OldHeight, n.NewHash, n.NewHeight)
		case chain.RelevantTx:
			err = walletdb.Update(w.db, func(tx walletdb.ReadWriteTx) error {
				return w.addRelevantTx(tx, n.TxRecord, n.Block)
			})
			strErrType = "RelevantTx"

		// The following are handled by the wallet's rescan
		// goroutines, so just pass them there.
		case *chain.RescanProgress, *chain.RescanFinished:
			w.rescanNotifications <- n
		}
		if err != nil {
			log.Errorf("Cannot handle chain server "+
				"notification %v: %v", strErrType, err)
		}
	}
	w.wg.Done()
}
Example #2
0
func (w *Wallet) handleChainNotifications() {
	sync := func(w *Wallet) {
		// At the moment there is no recourse if the rescan fails for
		// some reason, however, the wallet will not be marked synced
		// and many methods will error early since the wallet is known
		// to be out of date.
		err := w.syncWithChain()
		if err != nil && !w.ShuttingDown() {
			log.Warnf("Unable to synchronize wallet to chain: %v", err)
		}
	}

	for n := range w.chainSvr.Notifications() {
		var err error
		strErrType := ""

		switch n := n.(type) {
		case chain.ClientConnected:
			go sync(w)
		case chain.BlockConnected:
			w.connectBlock(wtxmgr.BlockMeta(n))
		case chain.BlockDisconnected:
			err = w.disconnectBlock(wtxmgr.BlockMeta(n))
		case chain.Reorganization:
			w.handleReorganizing(n.OldHash, n.OldHeight, n.NewHash, n.NewHeight)
		case chain.StakeDifficulty:
			err = w.handleStakeDifficulty(n.BlockHash, n.BlockHeight, n.StakeDiff)
			strErrType = "StakeDifficulty"
		case chain.RelevantTx:
			err = w.addRelevantTx(n.TxRecord, n.Block)

		// The following are handled by the wallet's rescan
		// goroutines, so just pass them there.
		case *chain.RescanProgress, *chain.RescanFinished:
			w.rescanNotifications <- n
		}
		if err != nil {
			log.Errorf("Cannot handle chain server "+
				"notification %v: %v", strErrType, err)
		}
	}
	w.wg.Done()
}