Example #1
0
def get_backup_subdir():
    '''
        Get subdir name if its in the data directory.

        >>> from blockchain_backup.bitcoin.preferences import get_preferences, save_preferences
        >>> from blockchain_backup.bitcoin.tests import utils as test_utils
        >>> test_utils.init_database()
        >>> get_backup_subdir()
        'backups'
        >>> prefs = get_preferences()
        >>> prefs.backup_dir = '/tmp/bitcoin/backups'
        >>> save_preferences(prefs)
        >>> get_backup_subdir() is None
        True
    '''
    from blockchain_backup.bitcoin.preferences import get_backup_dir, get_data_dir

    data_dir = get_data_dir()
    backup_dir = get_backup_dir()

    # get the name of the subdirectory of the backup
    # if its in the data directory
    index = backup_dir.find(data_dir)
    if index >= 0:
        backup_subdir = backup_dir[index + len(data_dir):]
        if backup_subdir.startswith(os.sep):
            backup_subdir = backup_subdir[1:]
        if backup_subdir.endswith(os.sep):
            backup_subdir = backup_subdir[:-1]
    else:
        backup_subdir = None

    return backup_subdir
Example #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)
Example #3
0
    def test_access_wallet_with_bad_data(self):
        '''
            Test access wallet with bad data
        '''
        MINUTE = 60
        WAIT_SECONDS = 10
        MAX_SECONDS = 3 * MINUTE

        # 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/access_wallet/')
        response = AccessWallet.as_view()(request)
        self.assertEqual(response.status_code, 200)
        self.assertTrue(
            b"<title>\nAccessing Bitcoin Core Wallet | Blockchain Backup\n</title>"
            in response.content)
        self.assertTrue(
            b"WARNING: Do not shut down your computer until Bitcoin-QT stops completely."
            in response.content)
        self.assertTrue(
            b'Bitcoin-QT will start in another window.' in response.content)
        self.assertFalse(
            b'Shutting down before this window says it is safe <em>could damage the blockchain</em>.'
            in response.content)

        done = False
        error_found = False
        error_message = None
        secs = 0
        while not done:
            shutdown, error_message = test_utils.check_bitcoin_log()
            if error_message:
                error = error_message.strip(' ')
                error_found = 'Fatal LevelDB error' in error or 'Error opening block database' in error
            done = shutdown or error_found or not get_backups_enabled(
            ) or secs > MAX_SECONDS
            if not done:
                sleep(WAIT_SECONDS)
                secs += WAIT_SECONDS

        if not error_found:
            shutdown, error_message = test_utils.check_bitcoin_log()
            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)

        test_utils.stop_bitcoin_qt()

        self.assertFalse(get_backups_enabled())
Example #4
0
    def get_page(self, request):
        # let's see what we know about the environment

        log('getting home page')

        clear_action_updates()

        # last block in django database; may be different from last in blockchain
        last_block_updated = state.get_last_block_updated()
        # ready if blockchain-backup has processed some blockchain data
        bcb_run_already = last_block_updated > 0
        bin_dir_ok = preferences.bin_dir_ok()
        data_dir = preferences.get_data_dir()
        backup_dir_ok, backup_dir_error = preferences.backup_dir_ok()
        backup_dir = preferences.get_backup_dir()
        last_bcb_version = state.get_latest_bcb_version()
        current_core_version = bitcoin_utils.get_bitcoin_version()
        last_core_version = state.get_latest_core_version()

        if bcb_run_already:
            data_dir_ok, __ = preferences.data_dir_ok()
        else:
            if data_dir and os.path.exists(data_dir):
                data_dir_ok, __ = preferences.data_dir_ok()
            else:
                data_dir_ok = False

        bitcoin_utils.check_for_updates()

        params = {
            'data_dir': data_dir,
            'data_dir_ok': data_dir_ok,
            'backup_dir': backup_dir,
            'backup_dir_ok': backup_dir_ok,
            'backup_dir_error': backup_dir_error,
            'last_bcb_version': last_bcb_version,
            'bcb_up_to_date': last_bcb_version >= BLOCKCHAIN_BACKUP_VERSION,
            'last_core_version': last_core_version,
            'core_up_to_date': last_core_version >= current_core_version,
            'need_backup': bitcoin_utils.get_next_backup_time() < now(),
            'last_backed_up_time': state.get_last_backed_up_time(),
        }
        #log('params: {}'.format(params))

        response = get_home_page_response(request, bcb_run_already, bin_dir_ok,
                                          params)

        return response
Example #5
0
    def get_page(self, request):
        error = None

        data_dir = preferences.get_data_dir()
        if not os.path.exists(data_dir):
            try:
                os.makedirs(data_dir)
            except:  # 'bare except' because it catches more than "except Exception"
                error = f'Unable to create {data_dir} as {whoami()}'

        if os.path.exists(data_dir):
            __, error = bitcoin_utils.is_dir_writeable(data_dir)

        if error is not None:
            log(error)
            messages.error(request, error)

        response = HttpResponseRedirect('/')

        return response
    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())
Example #7
0
def strip_testnet_from_data_dir(data_dir=None):
    '''
        Get the data dirname without
        the "testnet3" subdir, if appropriate.

        >>> from blockchain_backup.bitcoin.tests import utils as test_utils
        >>> test_utils.init_database()
        >>> strip_testnet_from_data_dir()
        '/tmp/bitcoin/data'
    '''
    from blockchain_backup.bitcoin.preferences import get_data_dir, get_extra_args

    if data_dir is None:
        data_dir = get_data_dir()

    use_test_net = constants.TESTNET_FLAG in get_extra_args()
    if use_test_net and data_dir.endswith(constants.TEST_NET_SUBDIR):
        new_data_dir = data_dir[:data_dir.rfind(constants.TEST_NET_SUBDIR)]

    else:
        new_data_dir = data_dir

    return new_data_dir
    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())