MultiBit HDTHE TECHNICAL RECOVERY LIBRARYmail@keychainx.io ↗

MultiBit HD / Technical library

INDEPENDENT KEYCHAINX RESOURCE

Backup tests: archive and retention behavior

Read the test setup alongside BackupManager to see the expected backup behavior and fixtures. Passing these historical tests would not independently establish modern dependency safety or compatibility with an arbitrary recovered backup.

By KeychainX · 20 September 2026 · Source revision 24a12b199a01

Source inspection only. Historical Java code; not executed or security-audited for this publication.

mbhd-core/src/test/java/org/multibit/hd/core/managers/BackupManagerTest.java

View the exact upstream file · Read raw source · License notices

SHA-256: af5defd8598f379038d901a5786a314ba1a0890439f88314eb9f50b34a4835f6

1/**2 * Copyright 2014 multibit.org3 *4 * Licensed under the MIT license (the "License");5 * you may not use this file except in compliance with the License.6 * You may obtain a copy of the License at7 *8 *    http://opensource.org/licenses/mit-license.php9 *10 * Unless required by applicable law or agreed to in writing, software11 * distributed under the License is distributed on an "AS IS" BASIS,12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13 * See the License for the specific language governing permissions and14 * limitations under the License.15 */16package org.multibit.hd.core.managers;1718import com.google.common.base.Optional;19import com.google.common.util.concurrent.Uninterruptibles;20import org.bitcoinj.core.Wallet;21import org.bitcoinj.crypto.MnemonicCode;22import org.junit.After;23import org.junit.Before;24import org.junit.Test;25import org.multibit.commons.files.SecureFiles;26import org.multibit.commons.utils.Dates;27import org.multibit.hd.brit.core.seed_phrase.Bip39SeedPhraseGenerator;28import org.multibit.hd.brit.core.seed_phrase.SeedPhraseGenerator;29import org.multibit.hd.core.config.Configurations;30import org.multibit.hd.core.dto.BackupSummary;31import org.multibit.hd.core.dto.WalletId;32import org.multibit.hd.core.dto.WalletIdTest;33import org.multibit.hd.core.dto.WalletSummary;34import org.multibit.hd.core.events.ShutdownEvent;35import org.multibit.hd.core.services.CoreServices;36import static org.mockito.Mockito.*;3738import java.io.File;39import java.util.List;40import java.util.concurrent.TimeUnit;4142import static org.fest.assertions.Assertions.assertThat;4344public class BackupManagerTest {4546  @Before47  public void setUp() throws Exception {4849    InstallationManager.unrestricted = true;5051    Configurations.currentConfiguration = Configurations.newDefaultConfiguration();5253    // Start the core services54    CoreServices.main(null);5556  }5758  @After59  public void tearDown() throws Exception {6061    // Order is important here62    CoreServices.shutdownNow(ShutdownEvent.ShutdownType.SOFT);6364    InstallationManager.shutdownNow(ShutdownEvent.ShutdownType.SOFT);65    BackupManager.INSTANCE.shutdownNow();66    WalletManager.INSTANCE.shutdownNow(ShutdownEvent.ShutdownType.SOFT);67  }6869  @Test70  public void testBackupWallet() throws Exception {7172    // Get the application directory73    File applicationDirectory = InstallationManager.getOrCreateApplicationDataDirectory();7475    // Create a random temporary directory in which to store the cloud backups76    File temporaryCloudBackupDirectory = SecureFiles.createTemporaryDirectory();7778    BackupManager backupManager = BackupManager.INSTANCE;7980    // Initialise the backup manager to point at the temporary cloud backup directory81    backupManager.initialise(applicationDirectory, Optional.of(temporaryCloudBackupDirectory));8283    // Create a temporary seed phrase84    SeedPhraseGenerator seedGenerator = new Bip39SeedPhraseGenerator();85    List<String> seedPhraseList = Bip39SeedPhraseGenerator.split(WalletIdTest.SEED_PHRASE_1);86    byte[] entropy = MnemonicCode.INSTANCE.toEntropy(seedPhraseList);87    byte[] seed = seedGenerator.convertToSeed(seedPhraseList);88    long nowInSeconds = Dates.nowInSeconds();89    String password = "credentials";9091    // Create a wallet summary (requires a backup manager to be in place)92    WalletSummary walletSummary = WalletManager93      .INSTANCE94      .getOrCreateMBHDSoftWalletSummaryFromEntropy(95              applicationDirectory,96              entropy,97              seed,98              nowInSeconds,99              password,100              "Example",101              "Example",102              true);103104    // Wallet manager does not initiate the backup105    BackupManager.INSTANCE.createRollingBackup(walletSummary, password);106    BackupManager.INSTANCE.createLocalBackup(walletSummary.getWalletId(), password);107    BackupManager.INSTANCE.createCloudBackup(walletSummary.getWalletId(), password);108109    // Check there are initially a single wallet backup for the wallet id of the created wallet110    List<BackupSummary> localBackups = BackupManager.INSTANCE.getLocalZipBackups(walletSummary.getWalletId());111112    assertThat(localBackups).isNotNull();113    assertThat(localBackups.size()).isEqualTo(1);114115    List<BackupSummary> cloudBackups = BackupManager.INSTANCE.getCloudBackups(walletSummary.getWalletId(), temporaryCloudBackupDirectory);116    assertThat(cloudBackups).isNotNull();117    assertThat(cloudBackups.size()).isEqualTo(1);118119    // Backup the wallet.120    // This zips the wallet root directory and adds a timestamp, then saves the file in both the local and cloud backup directories121    File localBackupFile = mock(File.class);122    localBackupFile = BackupManager.INSTANCE.createLocalBackup(walletSummary.getWalletId(), password);123    BackupManager.INSTANCE.createCloudBackup(walletSummary.getWalletId(), password);124125    // Check that a backup copy has been saved in the local backup directory126    // Load in the wallet backup and compare the wallets127    WalletId recreatedWalletId= BackupManager.INSTANCE.loadZipBackup(localBackupFile, Bip39SeedPhraseGenerator.split(WalletIdTest.SEED_PHRASE_1));128    assertThat(walletSummary.getWalletId()).isEqualTo(recreatedWalletId);129130    // Open131    String walletRoot = WalletManager.createWalletRoot(recreatedWalletId);132    File walletDirectory = WalletManager.getOrCreateWalletDirectory(applicationDirectory, walletRoot);133    WalletSummary recreatedWalletSummary = WalletManager.INSTANCE.loadFromWalletDirectory(walletDirectory, password);134    assertThat(recreatedWalletSummary).isNotNull();135    assertThat(recreatedWalletSummary.getWallet()).isNotNull();136137    // Load one of the rolling backups138    Wallet wallet = BackupManager.INSTANCE.loadRollingBackup(walletSummary.getWalletId(), password);139    assertThat(wallet).isNotNull();140  }141}

Read in context

Read the test setup alongside BackupManager to see the expected backup behavior and fixtures. Passing these historical tests would not independently establish modern dependency safety or compatibility with an arbitrary recovered backup.

Compare the callers, dependency versions and corresponding tests. The pinned file is one part of a larger application. Do not execute write, prune or migration routines against your only copy of a wallet.

Sources at the reviewed revision