Exemplo n.º 1
0
    def test_update_with_bitcoin_d_running(self):
        '''
            Test updating with bitcoind already running.
        '''
        # start bitcoind and wait for it to get started
        test_utils.start_bitcoind()
        while not is_bitcoind_running():
            sleep(1)
        log('bitcoind is running')

        request = self.factory.get('/bitcoin/update/')
        response = Update.as_view()(request)
        self.assertEqual(response.status_code, 200)
        self.assertTrue(
            b"<title>\nBitcoinD Is Running | Blockchain Backup\n</title>" in
            response.content)
        self.assertTrue(
            b'BitcoinD, one of the Bitcoin Core programs, appears to be running'
            in response.content)
        self.assertFalse(
            b'Bitcoin-QT, one of the Bitcoin Core programs, appears to be running'
            in response.content)
        self.assertFalse(
            b'Bitcoin-TX, one of the Bitcoin Core programs, appears to be running'
            in response.content)

        if is_bitcoind_running():
            test_utils.stop_bitcoind()

        self.assertTrue(get_backups_enabled())
Exemplo n.º 2
0
    def test_restore_with_missing_blocks(self):
        '''
            Test restore with missing blocks in blockchain.
        '''
        MINUTE = 60
        MAX_SECONDS = 2 * MINUTE

        # remove a block from the blockchain
        data_dir = preferences.get_data_dir()
        block_filename = os.path.join(data_dir, 'blocks', 'blk00000.dat')
        if os.path.exists(block_filename): os.remove(block_filename)

        __, preselected_date_dir = state.get_backup_dates_and_dirs()

        request = self.factory.get('/bitcoin/restore/')
        response = views.Restore.as_view()(request)
        self.assertEqual(response.status_code, 200)
        self.assertTrue(b"<title>\nAre you sure you want to restore the Bitcoin blockchain? | Blockchain Backup\n</title>" in response.content)
        self.assertTrue(b'Select backup to restore:' in response.content)
        self.assertTrue(b'<input type="submit" value="Yes, start restoring" name="yes-start-restoring-button" id="yes-start-restoring-id" alt="Yes, start restoring" class="btn btn-primary font-weight-bold " role="button"  title="Restore the blockchain now"/>' in response.content)
        self.assertTrue(b'<input type="submit" value="No, cancel restore" name="no-cancel-restore-button" id="no-cancel-restore-id" alt="No, cancel restore" class="btn btn-secondary font-weight-bold " role="button"  title="Do not restore the blockchain."/>' in response.content)

        client = Client()
        response = client.post('/bitcoin/restore/',
                               {'backup_dates_with_dirs': preselected_date_dir[0] })
        self.assertEqual(response.status_code, 200)
        self.assertTrue(b"<title>\nRestoring Bitcoin Blockchain | Blockchain Backup\n</title>" in response.content)
        self.assertTrue(b'WARNING: Do not shut down your computer until the restore finishes.' in response.content)
        self.assertTrue(b'Starting to restore the blockchain' in response.content)
        self.assertFalse(b'<input type="submit" value="Yes, start restoring" name="yes-start-restoring-button" id="yes-start-restoring-id" alt="Yes, start restoring" class="btn btn-primary font-weight-bold " role="button"  title="Restore the blockchain now"/>' in response.content)

        # wait until the restore finishes
        seconds = 0
        while not is_restore_running() and seconds < MAX_SECONDS:
            sleep(MINUTE)
            seconds += MINUTE

        # wait until bitcoind starts
        test_utils.start_bitcoind()
        seconds = 0
        while not is_bitcoind_running() and seconds < MAX_SECONDS:
            sleep(MINUTE)
            seconds += MINUTE

        self.assertTrue(is_bitcoind_running())

        # allow bitcoind to run for a while
        seconds = 0
        while is_bitcoind_running() and seconds < MAX_SECONDS:
            sleep(MINUTE)
            seconds += MINUTE

        if is_bitcoind_running():
            test_utils.stop_bitcoind()

        shutdown, error_message = test_utils.check_bitcoin_log(is_bitcoind_running)
        self.assertTrue(shutdown)
        self.assertTrue(error_message is None)
Exemplo n.º 3
0
    def update(self):
        '''
            Update the blockchain using bitcoind.

            Returns whether the update ended successfully and
                    whether a backup should start.

            If any errors while running, bitcoind, disable automatic
            backups so the user can decide how to proceed.
        '''

        ok = need_backup = False
        error_message = None

        self.manager.update_menu(constants.DISABLE_ITEM)

        self.manager.rename_logs()

        try:
            bitcoind_process, bitcoind_pid = self.start_bitcoind()
            if not self.is_interrupted():
                if bitcoind_process is None and bitcoind_pid is None:
                    self.manager.update_notice(self.ERROR_STARTING_BITCOIND)
                    self.manager.update_progress(self.UPDATE_UNEXPECTED_ERROR)
                    ok = False
                else:
                    need_backup = self.wait_while_updating(bitcoind_process)

                ok, error_message = self.stop_bitcoind(bitcoind_process,
                                                       bitcoind_pid,
                                                       need_backup)

        except BitcoinException as be:
            ok = False
            error_message = str(be)
            self.log(error_message)

        except:  # 'bare except' because it catches more than "except Exception"
            self.log(format_exc())

            # sometimes bitcoin exits with a non-zero return code,
            # but it was still ok, so check the logs
            ok, error_message = self.manager.bitcoin_finished_ok(
                is_bitcoind_running)

        if ok:
            if not need_backup:
                self.manager.update_progress('&nbsp;')
        elif error_message is not None:
            # don't allow any more backups until the user tells us it's ok
            state.set_backups_enabled(False)
            self.log('error while updating so stopping backups')

            if is_bitcoind_running():
                self.log('retry stopping bitcoind without showing progress')
                self.retry_stopping(show_progress=False)
            self.manager.update_subnotice(
                f'{self.BITCOIND_ERROR_LABEL} {error_message}')

        return ok, need_backup
Exemplo n.º 4
0
    def wait_for_shutdown(self, bitcoind_process, bitcoind_pid, need_backup):
        '''
            Wait for bitcoind to shutdown.

            >>> from blockchain_backup.bitcoin.tests import utils as test_utils
            >>> need_backup = False
            >>> test_utils.init_database()
            >>> update_task = UpdateTask()
            >>> update_task.manager = BitcoinManager(update_task.log_name)
            >>> bitcoind_process, bitcoind_pid = update_task.start_bitcoind()
            >>> update_task.wait_for_shutdown(bitcoind_process, bitcoind_pid, need_backup)
        '''

        try:
            if is_bitcoind_running():
                # get the last block number before we shut down
                self.current_block = self.manager.get_current_block(
                    show_progress=False)
                if need_backup:
                    self.manager.update_subnotice(self.STOP_UPDATE_FOR_BACKUP)
                self.manager.send_bitcoin_cli_cmd('stop', max_attempts=1)

            # wait until bitcoind terminates
            if bitcoind_process is None:
                try:
                    pid, returncode = os.waitpid(bitcoind_pid, os.P_WAIT)
                    self.log(f'waitpid {pid} return code: {returncode}')
                except ChildProcessError:
                    self.log('update_pid already dead')
            else:
                bitcoind_process.wait()
                self.log(
                    f'bitcoind return code: {bitcoind_process.returncode}')
        except:  # 'bare except' because it catches more than "except Exception"
            self.log(format_exc())
Exemplo n.º 5
0
    def retry_stopping(self, show_progress=True):
        '''
            Retry sending the stop command.
            At times, the process might end, but
            bitcoin itself is still running.

            >>> from blockchain_backup.bitcoin.tests import utils as test_utils
            >>> need_backup = False
            >>> test_utils.init_database()
            >>> update_task = UpdateTask()
            >>> update_task.manager = BitcoinManager(update_task.log_name)
            >>> update_task.retry_stopping()
        '''
        MAX_SECONDS = 30

        seconds = 0
        while is_bitcoind_running():

            sleep(1)
            seconds += 1
            if seconds > MAX_SECONDS:
                seconds = 0
                self.manager.send_bitcoin_cli_cmd('stop')
                if show_progress:
                    self.manager.update_progress(self.STOPPING_UPDATE)
Exemplo n.º 6
0
    def report_error(self, bitcoind_process, bitcoind_pid, error_message,
                     seconds):
        '''
            Report a serious error about stopping bitcoind.

            >>> from blockchain_backup.bitcoin.tests import utils as test_utils
            >>> test_utils.init_database()
            >>> update_task = UpdateTask()
            >>> update_task.manager = BitcoinManager(update_task.log_name)
            >>> bitcoind_process, bitcoind_pid = update_task.start_bitcoind()
            >>> need_backup = False
            >>> ok, error_message = update_task.stop_bitcoind(bitcoind_process, bitcoind_pid, need_backup)
            >>> update_task.report_error(bitcoind_process, bitcoind_pid, error_message, 60)
        '''
        # let the user know a serious error has happened
        if is_bitcoind_running():
            if bitcoind_process is None and bitcoind_pid is None:
                if error_message is None:
                    self.manager.update_progress(
                        f'Unable to stop bitcoind after {seconds/60} minutes')
            else:
                if bitcoind_process is None:
                    os.kill(bitcoind_pid, os.SIGTERM)
                else:
                    bitcoind_process.terminate()
                self.log('terminated bitcoin process')
        else:
            # clear the progress because we're no longer
            # waiting for bitcoind to shutdown
            self.manager.update_progress('&nbsp;')
Exemplo n.º 7
0
    def test_access_wallet_with_bitcoind_running(self):
        '''
            Test accessing the wallet with bitcoind already running.
        '''
        # start bitcoind and wait for it to get started
        test_utils.start_bitcoind()
        while not is_bitcoind_running():
            sleep(1)

        request = self.factory.get('/bitcoin/access_wallet/')
        response = AccessWallet.as_view()(request)
        self.assertEqual(response.status_code, 200)
        self.assertTrue(
            b"<title>\nBitcoinD Is Running | Blockchain Backup\n</title>" in
            response.content)
        self.assertTrue(
            b'BitcoinD, one of the Bitcoin Core programs, appears to be running'
            in response.content)
        self.assertFalse(
            b'Bitcoin-QT, one of the Bitcoin Core programs, appears to be running'
            in response.content)
        self.assertFalse(
            b'Bitcoin-TX, one of the Bitcoin Core programs, appears to be running'
            in response.content)

        test_utils.stop_bitcoind()
Exemplo n.º 8
0
        def wait(arg):
            ONE_MINUTE = 60

            secs = 0
            while ((utils.is_bitcoind_running()
                    or utils.is_bitcoin_qt_running()) and secs < ONE_MINUTE):
                sleep(1)
                secs += 1
            self.log(f'waited {secs} seconds before retrying "{arg}" command')
Exemplo n.º 9
0
def stop_bitcoin_core_apps():
    '''
        Stop all bitcoin core apps.

        >>> stop_bitcoin_core_apps()
    '''
    if bitcoin_utils.is_bitcoin_qt_running():
        stop_bitcoin_qt()

        # if it's still running, then kill it
        if bitcoin_utils.is_bitcoin_qt_running():
            bin_dir = os.path.join(virtualenv_dir(), 'bin')
            args = [os.path.join(bin_dir, 'killmatch'), bitcoin_utils.bitcoin_qt()]
            command.run(*args).stdout

    if bitcoin_utils.is_bitcoind_running():
        stop_bitcoind()

        # if it's still running, then kill it
        if bitcoin_utils.is_bitcoind_running():
            bin_dir = os.path.join(virtualenv_dir(), 'bin')
            args = [os.path.join(bin_dir, 'killmatch'), bitcoin_utils.bitcoind()]
            command.run(*args).stdout
Exemplo n.º 10
0
def stop_bitcoind():
    '''
        Stop bitcoind and determine if it ended properly.

        >>> init_database()
        >>> stop_bitcoind()
    '''
    while (bitcoin_utils.is_bitcoind_running()):
        sleep(5)
        send_bitcoin_cli_cmd('stop')

    # give it a little more time to settle down
    sleep(5)

    log(f'bitcoind running: {bitcoin_utils.is_bitcoind_running()}')
Exemplo n.º 11
0
    def test_restore_with_bad_backup(self):
        '''
            Test restore from a bad back up.
        '''
        MINUTE = 60
        MAX_SECONDS = 2 * MINUTE

        # change the data and backup dirs
        prefs = test_utils.get_preferences()
        prefs.data_dir = '/tmp/bitcoin/data-with-missing-file/testnet3/'
        prefs.backup_dir = '/tmp/bitcoin/data-with-missing-file/testnet3/backups/'
        preferences.save_preferences(prefs)

        __, preselected_date_dir = state.get_backup_dates_and_dirs()

        request = self.factory.get('/bitcoin/restore/')
        response = views.Restore.as_view()(request)
        self.assertEqual(response.status_code, 200)
        self.assertTrue(b"<title>\nAre you sure you want to restore the Bitcoin blockchain? | Blockchain Backup\n</title>" in response.content)
        self.assertTrue(b'Select backup to restore:' in response.content)
        self.assertTrue(b'<input type="submit" value="Yes, start restoring" name="yes-start-restoring-button" id="yes-start-restoring-id" alt="Yes, start restoring" class="btn btn-primary font-weight-bold " role="button"  title="Restore the blockchain now"/>' in response.content)
        self.assertTrue(b'<input type="submit" value="No, cancel restore" name="no-cancel-restore-button" id="no-cancel-restore-id" alt="No, cancel restore" class="btn btn-secondary font-weight-bold " role="button"  title="Do not restore the blockchain."/>' in response.content)

        client = Client()
        response = client.post('/bitcoin/restore/',
                               {'backup_dates_with_dirs': preselected_date_dir[0] })
        self.assertEqual(response.status_code, 200)
        self.assertTrue(b"<title>\nRestoring Bitcoin Blockchain | Blockchain Backup\n</title>" in response.content)
        self.assertTrue(b'WARNING: Do not shut down your computer until the restore finishes.' in response.content)
        self.assertTrue(b'Starting to restore the blockchain' in response.content)
        self.assertFalse(b'<input type="submit" value="Yes, start restoring" name="yes-start-restoring-button" id="yes-start-restoring-id" alt="Yes, start restoring" class="btn btn-primary font-weight-bold " role="button"  title="Restore the blockchain now"/>' in response.content)

        # wait until the restore finishes
        seconds = 0
        while not is_restore_running() and seconds < MAX_SECONDS:
            sleep(MINUTE)
            seconds += MINUTE

        self.assertFalse(is_bitcoind_running())
        self.assertFalse(state.get_backups_enabled())

        name = 'last-updated-2020-01-17 14:41'
        last_updated_file = os.path.join(prefs.backup_dir, 'level1', name)
        self.assertFalse(os.path.exists(last_updated_file))
Exemplo n.º 12
0
    def test_backup_with_bitcoind_running(self):
        '''
            Test backing up with bitcoind already running.
        '''
        test_utils.start_bitcoind()
        while not is_bitcoind_running():
            sleep(5)

        request = self.factory.get('/bitcoin/backup/')
        response = views.Backup.as_view()(request)

        # stop bitcoin in case any tests fail
        test_utils.stop_bitcoind()

        self.assertEqual(response.status_code, 200)
        self.assertTrue(b"<title>\nBitcoinD Is Running | Blockchain Backup\n</title>" in response.content)
        self.assertTrue(b'BitcoinD, one of the Bitcoin Core programs, appears to be running' in response.content)
        self.assertFalse(b'Bitcoin-QT, one of the Bitcoin Core programs, appears to be running' in response.content)
        self.assertFalse(b'Bitcoin-TX, one of the Bitcoin Core programs, appears to be running' in response.content)
Exemplo n.º 13
0
    def test_restore_with_bitcoind_running(self):
        '''
            Test restoring with bitcoind already running.
        '''
        test_utils.start_bitcoind()
        while not is_bitcoind_running():
            sleep(5)

        request = self.factory.get('/bitcoin/restore/')
        response = views.Restore.as_view()(request)

        # stop the task before we start tests in case something fails
        test_utils.stop_bitcoind()

        self.assertEqual(response.status_code, 200)
        self.assertTrue(b"<title>\nBitcoinD Is Running | Blockchain Backup\n</title>" in response.content)
        self.assertTrue(b'BitcoinD, one of the Bitcoin Core programs, appears to be running' in response.content)
        self.assertFalse(b'Bitcoin-QT, one of the Bitcoin Core programs, appears to be running' in response.content)
        self.assertFalse(b'Bitcoin-TX, one of the Bitcoin Core programs, appears to be running' in response.content)
Exemplo n.º 14
0
    def test_update_with_missing_links(self):
        '''
            Start the update with missing links.
        '''
        # remove links from the chainstate
        dirname = os.path.join(get_data_dir(), 'chainstate')
        entries = os.scandir(dirname)
        for entry in entries:
            if entry.name.endswith('.ldb'):
                os.remove(entry.path)

        request = self.factory.get('/bitcoin/update/')
        response = Update.as_view()(request)
        self.assertEqual(response.status_code, 200)
        self.assertTrue(
            b"<title>\nUpdating Bitcoin's Blockchain | Blockchain Backup\n</title>"
            in response.content)
        self.assertTrue(b"WARNING: Don't shut down your computer before you" in
                        response.content)
        self.assertTrue(
            b'<a class="btn btn-secondary " role="button" id="stop_button" href="/bitcoin/interrupt_update/" title="Click to stop updating the blockchain">Stop update</a>'
            in response.content)
        self.assertTrue(
            b'Shutting down before this window says it is safe <em>could damage the blockchain</em>.'
            in response.content)

        sleep(60)

        self.assertFalse(is_bitcoind_running())

        shutdown, error_message = test_utils.check_bitcoin_log(
            is_bitcoind_running)
        self.assertTrue(shutdown)
        log(error_message)
        self.assertTrue(
            'Aborted block database rebuild. Exiting.' in error_message
            or 'Error opening block database.' in error_message
            or 'Fatal LevelDB error' in error_message)

        self.assertFalse(get_backups_enabled())
Exemplo n.º 15
0
    def send_bitcoin_cli_cmd(self, arg, max_attempts=1):
        '''
            Send a command via bitcoin-cli.

            >>> from blockchain_backup.bitcoin.tests import utils as test_utils
            >>> test_utils.init_database()
            >>> manager = BitcoinManager('blockchain_backup.bitcoin.manager.log')
            >>> manager.send_bitcoin_cli_cmd('getblockchaininfo')
            -1
        '''
        def wait(arg):
            ONE_MINUTE = 60

            secs = 0
            while ((utils.is_bitcoind_running()
                    or utils.is_bitcoin_qt_running()) and secs < ONE_MINUTE):
                sleep(1)
                secs += 1
            self.log(f'waited {secs} seconds before retrying "{arg}" command')

        command_args = self.get_bitcoin_cli_cmd(arg)

        attempts = 0
        result = -1
        while (attempts < max_attempts and result == -1 and
               (utils.is_bitcoind_running() or utils.is_bitcoin_qt_running())):

            try:
                result = command.run(*command_args).stdout
                if attempts > 0:
                    self.log(f'resent "{arg}" command {attempts} times')
            except CalledProcessError as cpe:
                attempts += 1
                self.handle_bitcoin_cli_error(arg, cpe)

                if attempts < max_attempts:
                    wait(arg)

        return result
Exemplo n.º 16
0
def start_bitcoind():
    '''
        Start bitcoind as a daemon.

        >>> init_database()
        >>> start_bitcoind()
        >>> stop_bitcoind()
    '''

    bin_dir, data_dir = preferences.get_bitcoin_dirs()

    command_args = []
    cmd = os.path.join(bin_dir, bitcoin_utils.bitcoind())
    command_args.append(cmd)

    data_dir = bitcoin_utils.strip_testnet_from_data_dir(data_dir=data_dir)
    command_args.append(f'-datadir={data_dir}')

    # don't allow any interaction with the user's wallet
    command_args.append('-disablewallet')

    extra_args = preferences.get_extra_args()
    if len(extra_args) > 0:
        for extra_arg in extra_args:
            command_args.append(extra_arg)

    command_args.append('-daemon')

    command.background(*command_args)
    log(f'running in background: {command_args}')

    # give bitcoind time to start
    secs = 0
    while (not bitcoin_utils.is_bitcoind_running() and secs < 5):
        sleep(1)
        secs += 1
Exemplo n.º 17
0
    def test_update_with_missing_blocks(self):
        '''
            Start the update with missing blocks.
        '''
        # remove a block from the blockchain
        block_filename = os.path.join(get_data_dir(), 'blocks', 'blk00000.dat')
        if os.path.exists(block_filename):
            os.remove(block_filename)

        request = self.factory.get('/bitcoin/update/')
        response = Update.as_view()(request)
        self.assertEqual(response.status_code, 200)
        self.assertTrue(
            b"<title>\nUpdating Bitcoin's Blockchain | Blockchain Backup\n</title>"
            in response.content)
        self.assertTrue(b"WARNING: Don't shut down your computer before you" in
                        response.content)
        self.assertTrue(
            b'<a class="btn btn-secondary " role="button" id="stop_button" href="/bitcoin/interrupt_update/" title="Click to stop updating the blockchain">Stop update</a>'
            in response.content)
        self.assertTrue(
            b'Shutting down before this window says it is safe <em>could damage the blockchain</em>.'
            in response.content)

        sleep(60)

        self.assertFalse(is_bitcoind_running())

        shutdown, error_message = test_utils.check_bitcoin_log(
            is_bitcoind_running)
        self.assertTrue(shutdown)
        error = error_message.strip(' ')
        error_found = 'Fatal LevelDB error' in error or 'Error opening block database' in error
        self.assertTrue(error_found)

        self.assertFalse(get_backups_enabled())
Exemplo n.º 18
0
    def wait_for_status(self):
        '''
            Wait for bitcoin to clean up.

            Returns
                True if bitcoin shutdown successfully; otherwise, False.
                Error message from bitcoind if this is one; otherwise, None.
                Seconds waiting.

            >>> from blockchain_backup.bitcoin.tests import utils as test_utils
            >>> need_backup = False
            >>> test_utils.init_database()
            >>> update_task = UpdateTask()
            >>> update_task.manager = BitcoinManager(update_task.log_name)
            >>> update_task.wait_for_status()
            (True, None, 0)
        '''
        WAIT_SECONDS = 10
        MAX_SECONDS = 60

        # if bitcoin is not running, then give it more time to see
        # if the debug log is updated with the status
        seconds = 0
        ok, error_message = self.manager.check_bitcoin_log(is_bitcoind_running)
        while (not ok and seconds < MAX_SECONDS and not is_bitcoind_running()):

            sleep(WAIT_SECONDS)
            seconds += WAIT_SECONDS
            ok, error_message = self.manager.check_bitcoin_log(
                is_bitcoind_running)

        if seconds >= MAX_SECONDS:
            self.log(f'waited {seconds} seconds for bitcoin to finish.')
            self.log(f'is_bitcoind_running: {is_bitcoind_running()}')

        return ok, error_message, seconds
Exemplo n.º 19
0
    def test_update(self):
        '''
            Start the update via views,
            wait a few minutes, then interrupt it.
        '''

        request = self.factory.get('/bitcoin/update/')
        response = Update.as_view()(request)
        self.assertEqual(response.status_code, 200)
        self.assertTrue(
            b"<title>\nUpdating Bitcoin's Blockchain | Blockchain Backup\n</title>"
            in response.content)
        self.assertTrue(b"WARNING: Don't shut down your computer before you" in
                        response.content)
        self.assertTrue(
            b'<a class="btn btn-secondary " role="button" id="stop_button" href="/bitcoin/interrupt_update/" title="Click to stop updating the blockchain">Stop update</a>'
            in response.content)
        self.assertTrue(
            b'Shutting down before this window says it is safe <em>could damage the blockchain</em>.'
            in response.content)

        sleep(180)
        if is_bitcoind_running():
            test_utils.stop_bitcoind()
Exemplo n.º 20
0
    def wait_while_updating(self, bitcoind_process):
        '''
            Wait for the blockchain to be updated.

            >>> from blockchain_backup.bitcoin.tests import utils as test_utils
            >>> test_utils.init_database()
            >>> update_task = UpdateTask()
            >>> update_task.manager = BitcoinManager(update_task.log_name)
            >>> bitcoind_process, bitcoind_pid = update_task.start_bitcoind()
            >>> need_backup = update_task.wait_while_updating(bitcoind_process)
            >>> print(need_backup)
            False
            >>> update_task.stop_bitcoind(bitcoind_process, bitcoind_pid, need_backup)
            (False, ' Error opening block database.\\n')
        '''
        def get_secs_to_wait():
            ''' Wait longer if no real data available yet. '''

            if self.current_block > 0:
                secs_to_wait = WAIT_SECONDS
            else:
                secs_to_wait = WAIT_SECONDS * 2

            return secs_to_wait

        WAIT_SECONDS = 30  # seconds

        self.log('waiting while updating blockchain')

        # give the system a few seconds to get it started
        secs = 0
        while (not is_bitcoind_running() and secs < (WAIT_SECONDS * 6)
               and not self.is_interrupted()):

            sleep(WAIT_SECONDS)
            secs += WAIT_SECONDS

        self.current_block = self.manager.get_current_block()
        need_backup = need_to_backup(self.manager.data_dir, self.current_block)
        secs_to_wait = get_secs_to_wait()
        while (is_bitcoind_running() and not need_backup
               and not self.is_interrupted()):

            try:
                if bitcoind_process is None:
                    sleep(secs_to_wait)
                else:
                    bitcoind_process.wait(secs_to_wait)
            except TimeoutExpired:
                pass

            if is_bitcoind_running() and not self.is_interrupted():
                self.current_block = self.manager.get_current_block()
                need_backup = need_to_backup(self.manager.data_dir,
                                             self.current_block)
                secs_to_wait = get_secs_to_wait()

        self.log(f'is_bitcoind_running: {is_bitcoind_running()}')
        self.log(f'need_backup: {need_backup}')
        self.log(f'is_interrupted: {self.is_interrupted()}')
        self.log(f'finished waiting; need backup: {need_backup}')

        return need_backup
Exemplo n.º 21
0
    def get_page(self, request):

        global update_task

        log('trying to update blockchain')

        clear_action_updates()

        # check that no other bitcoin-core app is running
        if (bitcoin_utils.is_bitcoin_qt_running()
                or bitcoin_utils.is_bitcoin_tx_running()
                or (bitcoin_utils.is_bitcoind_running() and not updating())):
            response = warn_core_running(request)

        # tell user if another blockchain_backup app is running
        elif bitcoin_utils.is_backup_running(
        ) or bitcoin_utils.is_restore_running():
            response = warn_bcb_app_running(request)

        # tell user if another task is running
        elif accessing_wallet() or backing_up() or restoring():
            response = warn_bcb_task_running(request)

        else:
            NOTICE1 = 'WARNING: Don\'t shut down your computer before you <a class="btn btn-secondary " role="button"'
            NOTICE2 = 'id="stop_button" href="/bitcoin/interrupt_update/" title="Click to stop updating the blockchain">Stop update</a>'
            NOTICE = f'{NOTICE1} {NOTICE2}'

            context = bitcoin_utils.get_blockchain_context()

            data_dir_ok, error = preferences.data_dir_ok()
            if not preferences.bin_dir_ok():
                context['notice'] = BAD_BIN_DIR
                log(BAD_BIN_DIR)
            elif not data_dir_ok:
                context['notice'] = BAD_DATA_DIR
                log(error)
            else:
                context['header'] = "Updating Bitcoin's blockchain"
                context[
                    'notice'] = 'WARNING: Don\'t shut down your computer before you <a class="btn btn-secondary " role="button" id="stop_button" href="/bitcoin/interrupt_update/" title="Click to stop updating the blockchain">Stop update</a>'
                context[
                    'subnotice'] = 'Shutting down before this window says it is safe <em>could damage the blockchain</em>.'
                context['progress'] = 'Starting to update the blockchain'
                context['update_interval'] = '5000'

                if updating():
                    log('already updating blockchain')

                else:
                    from blockchain_backup.bitcoin.update import UpdateTask

                    update_task = UpdateTask()
                    update_task.start()
                    log('UpdateTask started')

            # make sure the button doesn't appear any more
            bitcoin_utils.send_socketio_message('button', ' ')

            log(f'context: {context}')
            response = render(request, 'bitcoin/update.html', context=context)

        return response
Exemplo n.º 22
0
    def get_page(self, request):

        global accessing_wallet_task

        log('accessing bitcoin interactively')

        clear_action_updates()

        # it's ok if bitcoin-qt is running in our task
        if (bitcoin_utils.is_bitcoind_running()
                or bitcoin_utils.is_bitcoin_tx_running()
                or (bitcoin_utils.is_bitcoin_qt_running()
                    and not accessing_wallet())):
            response = warn_core_running(request)

        # tell user if another app is running
        elif bitcoin_utils.is_backup_running(
        ) or bitcoin_utils.is_restore_running():
            response = warn_bcb_app_running(request)

        # tell user if another task is running
        elif updating() or backing_up() or restoring():
            response = warn_bcb_task_running(request)

        else:
            SUBNOTICE1 = "Waiting until you exit Bitcoin-QT.<p>Bitcoin-QT will start in another window."
            SUBNOTICE2 = "You can send and receive transactions from that window."
            SUBNOTICE3 = "After you exit Bitcoin-QT, Blockchain Backup will continue updating the blockchain until it's time to back it up."
            SUBNOTICE4 = "Don't forget to back up your wallet routinely."
            SUBNOTICE = f'{SUBNOTICE1} {SUBNOTICE2} {SUBNOTICE3} {SUBNOTICE4}'

            context = bitcoin_utils.get_blockchain_context()

            data_dir_ok, error = preferences.data_dir_ok()
            if not preferences.bin_dir_ok():
                context['notice'] = BAD_BIN_DIR
            elif not data_dir_ok:
                context['notice'] = BAD_DATA_DIR
                context['subnotice'] = error
            else:
                context[
                    'header'] = "Accessing Bitcoin Core Wallet Interactively"
                context[
                    'notice'] = 'WARNING: Do not shut down your computer until Bitcoin-QT stops completely.'
                context['subnotice'] = SUBNOTICE

                if accessing_wallet():
                    log('already accessing wallet')

                else:
                    from blockchain_backup.bitcoin.access_wallet import AccessWalletTask

                    accessing_wallet_task = AccessWalletTask()
                    accessing_wallet_task.start()
                    log('access wallet started')

                # make sure the button doesn't appear any more
                bitcoin_utils.send_socketio_message('button', ' ')

            response = render(request,
                              'bitcoin/access_wallet.html',
                              context=context)

        return response
Exemplo n.º 23
0
    def start_bitcoind(self):
        '''
            Start bitcoind as a daemon.

            >>> from blockchain_backup.bitcoin.tests import utils as test_utils
            >>> need_backup = False
            >>> test_utils.init_database()
            >>> update_task = UpdateTask()
            >>> update_task.manager = BitcoinManager(update_task.log_name)
            >>> bitcoind_process, bitcoind_pid = update_task.start_bitcoind()
            >>> update_task.stop_bitcoind(bitcoind_process, bitcoind_pid, need_backup)
            (False, ' Error opening block database.\\n')
        '''
        if is_bitcoind_running():
            bitcoind_process = None
            bitcoind_pid = get_pid(bitcoind())
            if bitcoind_pid is None:
                sleep(5)
                bitcoind_pid = get_pid(bitcoind())
            self.log(f'bitcoind is already running using pid: {bitcoind_pid}')
        else:
            bitcoind_pid = None
            command_args = []

            if self.manager.bin_dir is None:
                command_args.append(bitcoind())
                ok = True
            else:
                cmd = os.path.join(self.manager.bin_dir, bitcoind())
                command_args.append(cmd)
                ok = os.path.exists(cmd)

            if ok:
                extra_args = preferences.get_extra_args()
                use_test_net = '-testnet' in extra_args

                if self.manager.data_dir is not None:
                    data_dir = self.manager.data_dir
                    if use_test_net and data_dir.endswith(
                            constants.TEST_NET_SUBDIR):
                        data_dir = data_dir[:data_dir.rfind(constants.
                                                            TEST_NET_SUBDIR)]
                    command_args.append(f'-datadir={data_dir}')

                # don't allow any interaction with the user's wallet
                command_args.append('-disablewallet')

                if extra_args:
                    for extra_arg in extra_args:
                        command_args.append(extra_arg)

                command_args.append('-daemon')

                try:
                    bitcoind_process = Popen(command_args)
                    self.log(
                        f'bitcoind started: {bitcoind_process is not None}')
                except FileNotFoundError as fnfe:
                    raise BitcoinException(str(fnfe))

            else:
                bitcoind_process = None
                self.log(
                    f'{bitcoind()} does not exist in {self.manager.bin_dir}')

        state.set_start_access_time(now())

        return bitcoind_process, bitcoind_pid