@Before
  public void setUp() throws Exception {
    multiBitDirectory = createMultiBitRuntime();

    // Set the application data directory to be the one we just created.
    ApplicationDataDirectoryLocator applicationDataDirectoryLocator =
        new ApplicationDataDirectoryLocator(multiBitDirectory);

    // Create MultiBit controller
    final CreateControllers.Controllers controllers =
        CreateControllers.createControllers(applicationDataDirectoryLocator);
    controller = controllers.bitcoinController;

    log.debug("Creating Bitcoin service");
    // Create the MultiBitService that connects to the bitcoin network.
    MultiBitService multiBitService = new MultiBitService(controller);
    controller.setMultiBitService(multiBitService);

    // Add the simple view system (no Swing).
    simpleViewSystem = new SimpleViewSystem();
    controllers.coreController.registerViewSystem(simpleViewSystem);

    log.debug("Waiting for peer connection. . . ");
    while (!simpleViewSystem.isOnline()) {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    log.debug("Now online.");
  }
  @Test
  public void testReplayManagerSyncSingleWallet() throws Exception {
    // Get the system property runFunctionalTest to see if the functional
    // tests need running.
    String runFunctionalTests = System.getProperty(Constants.RUN_FUNCTIONAL_TESTS_PARAMETER);
    if (Boolean.TRUE.toString().equalsIgnoreCase(runFunctionalTests)) {
      // Date format is UTC with century, T time separator and Z for UTC
      // timezone.
      formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH);
      formatter.setTimeZone(TimeZone.getTimeZone("UTC"));

      // Initialise replay manager
      ReplayManager replayManager = ReplayManager.INSTANCE;
      assertNotNull(replayManager);

      replayManager.initialise(controller, true);

      String replayWalletPath =
          multiBitDirectory.getAbsolutePath() + File.separator + "replay.wallet";

      // Create a new wallet.
      Wallet replayWallet = new Wallet(NetworkParameters.prodNet());

      // Add in the replay key.
      DumpedPrivateKey replayDumpedPrivateKey =
          new DumpedPrivateKey(NetworkParameters.prodNet(), REPLAY1_PRIVATE_KEY);
      ECKey replayKey = replayDumpedPrivateKey.getKey();
      replayKey.setCreationTimeSeconds(formatter.parse(START_OF_REPLAY_PERIOD).getTime() / 1000);
      log.debug("replayPrivateKey getCreationTimeSeconds = " + replayKey.getCreationTimeSeconds());

      replayWallet.addKey(replayKey);
      WalletData perWalletModelData = new WalletData();
      perWalletModelData.setWalletInfo(
          new WalletInfoData(replayWalletPath, replayWallet, MultiBitWalletVersion.PROTOBUF));
      perWalletModelData.setWallet(replayWallet);
      perWalletModelData.setWalletFilename(replayWalletPath);
      perWalletModelData.setWalletDescription("testReplayManagerSyncSingleWallet test");
      controller.getModel().getPerWalletModelDataList().add(perWalletModelData);

      log.debug("Replay wallet before replay = \n" + replayWallet.toString());

      assertEquals(BALANCE_AT_START, replayWallet.getBalance());

      log.debug("Replaying blockchain");
      // Create a ReplayTask to replay the replay wallet from the
      // START_OF_REPLAY_PERIOD.
      List<WalletData> perWalletModelDataList = new ArrayList<WalletData>();
      perWalletModelDataList.add(perWalletModelData);

      ReplayTask replayTask =
          new ReplayTask(
              perWalletModelDataList,
              formatter.parse(START_OF_REPLAY_PERIOD),
              ReplayTask.UNKNOWN_START_HEIGHT);
      replayManager.offerReplayTask(replayTask);

      // Run for a while.
      log.debug("Twiddling thumbs for 60 seconds ...");
      Thread.sleep(60000);
      log.debug("... 60 seconds later.");

      // Check the wallet - there should be some transactions in there.
      if (replayWallet.getTransactions(true).size() > 0) {
        // We are done.
      } else {
        // Run for a while longer.
        log.debug("Twiddling thumbs for another 60 seconds ...");
        Thread.sleep(60000);
        log.debug("... 60 seconds later.");
        if (replayWallet.getTransactions(true).size() > 0) {
          // We are done.
        } else {
          if (simpleViewSystem.getNumberOfBlocksDownloaded() > 0) {
            // Well it tried but probably got a slow connection -
            // give it a pass.
          } else {
            fail("No blocks were downloaded on replay");
          }
        }
      }

      // Print out replay wallet after replay.
      log.debug("Replay wallet after replay = \n" + replayWallet);
    } else {
      log.debug(
          "Not running functional test: ReplayManagerTest#testReplayManagerSyncSingleWallet. Add '-DrunFunctionalTests=true' to run");
    }
  }
  @Test
  public void testReplayMiningTransaction() throws Exception {
    // Get the system property runFunctionalTest to see if the functional tests need running.
    String runFunctionalTests = System.getProperty(Constants.RUN_FUNCTIONAL_TESTS_PARAMETER);
    if (Boolean.TRUE.toString().equalsIgnoreCase(runFunctionalTests)) {

      // Date format is UTC with century, T time separator and Z for UTC timezone.
      formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH);
      formatter.setTimeZone(TimeZone.getTimeZone("UTC"));

      File multiBitDirectory = createMultiBitRuntime();

      // Set the application data directory to be the one we just created.
      ApplicationDataDirectoryLocator applicationDataDirectoryLocator =
          new ApplicationDataDirectoryLocator(multiBitDirectory);
      log.debug("applicationDataDirectoryLocator = " + applicationDataDirectoryLocator);

      // Create MultiBit controller.
      final CreateControllers.Controllers controllers =
          CreateControllers.createControllers(applicationDataDirectoryLocator);

      log.debug("Creating Bitcoin service");
      // Create the MultiBitService that connects to the bitcoin network.
      MultiBitService multiBitService = new MultiBitService(controllers.bitcoinController);
      log.debug("multiBitService = " + multiBitService);

      controllers.bitcoinController.setMultiBitService(multiBitService);

      // Add the simple view system (no Swing).
      SimpleViewSystem simpleViewSystem = new SimpleViewSystem();
      controllers.coreController.registerViewSystem(simpleViewSystem);
      log.debug("simpleViewSystem = " + simpleViewSystem);

      ReplayManager.INSTANCE.initialise(controllers.bitcoinController);

      //
      // MultiBit runtime is now setup and running.
      //

      String miningWalletPath =
          multiBitDirectory.getAbsolutePath() + File.separator + "mining.wallet";

      // Create a new wallet.
      Wallet miningWallet = new Wallet(NetworkParameters.prodNet());

      // Add in the mining key that has the coinbase transactions.
      DumpedPrivateKey miningPrivateKey =
          new DumpedPrivateKey(NetworkParameters.prodNet(), MINING_PRIVATE_KEY);

      miningWallet.addKey(miningPrivateKey.getKey());
      WalletData perWalletModelData = new WalletData();
      perWalletModelData.setWalletInfo(
          new WalletInfoData(miningWalletPath, MultiBitWalletVersion.PROTOBUF));
      perWalletModelData.setWallet(miningWallet);
      perWalletModelData.setWalletFilename(miningWalletPath);
      perWalletModelData.setWalletDescription("testReplayMiningTransaction test");

      // Save the new wallet.
      controllers
          .bitcoinController
          .getFileHandler()
          .savePerWalletModelData(perWalletModelData, true);

      // Get the multibitService to load it up and hook it up to the blockchain.
      controllers.bitcoinController.getMultiBitService().addWalletFromFilename(miningWalletPath);
      controllers.bitcoinController.getModel().setActiveWalletByFilename(miningWalletPath);

      log.debug("Mining wallet = \n" + miningWallet.toString());

      assertEquals(BALANCE_AT_START, miningWallet.getBalance());

      // Wait for a peer connection.
      log.debug("Waiting for peer connection. . . ");
      while (!simpleViewSystem.isOnline()) {
        Thread.sleep(1000);
      }
      log.debug("Now online.");

      log.debug("Replaying blockchain");
      // multiBitService.replayBlockChain(formatter.parse(START_OF_REPLAY_PERIOD));
      List<WalletData> perWalletModelDataList = new ArrayList<WalletData>();
      perWalletModelDataList.add(
          controllers.bitcoinController.getModel().getActivePerWalletModelData());
      ReplayTask replayTask =
          new ReplayTask(
              perWalletModelDataList,
              formatter.parse(START_OF_REPLAY_PERIOD),
              ReplayTask.UNKNOWN_START_HEIGHT);
      ReplayManager.INSTANCE.offerReplayTask(replayTask);

      // Run for a minute.
      log.debug("Twiddling thumbs for a minute ...");
      Thread.sleep(60000);
      log.debug("... one minute later.");

      // Check new balance on wallet - estimated balance should be at least the
      // expected (may have later tx too)..

      log.debug(
          "Mining wallet estimated balance is:\n"
              + controllers
                  .bitcoinController
                  .getModel()
                  .getActiveWallet()
                  .getBalance(BalanceType.ESTIMATED)
                  .toString());
      log.debug(
          "Mining wallet spendable balance is:\n"
              + controllers.bitcoinController.getModel().getActiveWallet().getBalance().toString());
      log.debug(
          "Mining wallet is:\n"
              + controllers.bitcoinController.getModel().getActiveWallet().toString());
      assertTrue(
          "Estimated balance of mining wallet is incorrect",
          BALANCE_AFTER_REPLAY.compareTo(
                  controllers
                      .bitcoinController
                      .getModel()
                      .getActiveWallet()
                      .getBalance(BalanceType.ESTIMATED))
              <= 0);
      // assertTrue("Available balance of mining wallet is incorrect",
      // BigInteger.ZERO.compareTo(controller.getModel().getActiveWallet().getBalance()) == 0);

      // See if the first transaction is a coinbase.
      miningWallet = controllers.bitcoinController.getModel().getActiveWallet();

      Set<Transaction> transactions = miningWallet.getTransactions(true);
      assertTrue("Transactions are missing", !(transactions == null || transactions.isEmpty()));
      Transaction transaction = transactions.iterator().next();
      assertNotNull("First transaction is null", transaction);
      System.out.println("First transaction before roundtrip\n" + transaction);

      assertTrue(
          "The first transaction in the wallet is not a coinbase but it should be",
          transaction.isCoinBase());

      // Force save the wallet, reload it and check the transaction is still coinbase.
      controllers
          .bitcoinController
          .getFileHandler()
          .savePerWalletModelData(perWalletModelData, true);

      WalletData rebornPerWalletModelData =
          controllers.bitcoinController.getFileHandler().loadFromFile(new File(miningWalletPath));
      assertNotNull("No reborn perWalletModelData", rebornPerWalletModelData);
      ;
      assertNotNull("No reborn wallet", rebornPerWalletModelData.getWallet());

      Wallet rebornMiningWallet = rebornPerWalletModelData.getWallet();

      // See if the first transaction in the reborn wallet is a coinbase.
      Set<Transaction> rebornTransactions = rebornMiningWallet.getTransactions(true);
      assertTrue(
          "No reborn transactions", !(rebornTransactions == null || rebornTransactions.isEmpty()));
      Transaction rebornTransaction = rebornTransactions.iterator().next();
      assertNotNull("No reborn first transaction", rebornTransaction);
      System.out.println("First transaction after roundtrip\n" + rebornTransaction);

      assertTrue(
          "The first transaction in the wallet is not a coinbase but it should be",
          rebornTransaction.isCoinBase());

      // Tidy up.
      multiBitService.getPeerGroup().stop();

      controllers
          .bitcoinController
          .getFileHandler()
          .deleteWalletAndWalletInfo(
              controllers.bitcoinController.getModel().getActivePerWalletModelData());
    } else {
      log.debug(
          "Not running functional test: MiningCoinBaseTransactionsSeenTest#testReplayMiningTransaction. Add '-DrunFunctionalTests=true' to run");
    }
  }