예제 #1
0
  public void addNewKeyToWallet() {
    wallet.addKey(new ECKey());

    backupKeys();

    prefs.edit().putBoolean(Constants.PREFS_KEY_REMIND_BACKUP, true).commit();
  }
예제 #2
0
  private static Wallet readKeys(@Nonnull final InputStream is) throws IOException {
    final BufferedReader in = new BufferedReader(new InputStreamReader(is, Constants.UTF_8));
    final List<ECKey> keys = WalletUtils.readKeys(in);
    in.close();

    final Wallet wallet = new Wallet(Constants.NETWORK_PARAMETERS);
    for (final ECKey key : keys) wallet.addKey(key);

    return wallet;
  }
  public void setUp(BlockStore blockStore) throws Exception {
    BriefLogFormatter.init();

    unitTestParams = UnitTestParams.get();
    Wallet.SendRequest.DEFAULT_FEE_PER_KB = BigInteger.ZERO;
    this.blockStore = blockStore;
    wallet = new Wallet(unitTestParams);
    key = new ECKey();
    address = key.toAddress(unitTestParams);
    wallet.addKey(key);
    blockChain = new BlockChain(unitTestParams, wallet, blockStore);

    startPeerServers();
    if (clientType == ClientType.NIO_CLIENT_MANAGER
        || clientType == ClientType.BLOCKING_CLIENT_MANAGER) {
      channels.startAsync();
      channels.awaitRunning();
    }

    socketAddress = new InetSocketAddress("127.0.0.1", 1111);
  }
  /**
   * Loads wallet data from the given protocol buffer and inserts it into the given Wallet object.
   * This is primarily useful when you wish to pre-register extension objects. Note that if loading
   * fails the provided Wallet object may be in an indeterminate state and should be thrown away.
   *
   * @throws IOException if there is a problem reading the stream.
   * @throws IllegalArgumentException if the wallet is corrupt.
   */
  public void readWallet(Protos.Wallet walletProto, Wallet wallet) throws IOException {
    // TODO: This method should throw more specific exception types than IllegalArgumentException.
    // Read the scrypt parameters that specify how encryption and decryption is performed.
    if (walletProto.hasEncryptionParameters()) {
      Protos.ScryptParameters encryptionParameters = walletProto.getEncryptionParameters();
      wallet.setKeyCrypter(new KeyCrypterScrypt(encryptionParameters));
    }

    if (walletProto.hasDescription()) {
      wallet.setDescription(walletProto.getDescription());
    }

    // Read all keys
    for (Protos.Key keyProto : walletProto.getKeyList()) {
      if (!(keyProto.getType() == Protos.Key.Type.ORIGINAL
          || keyProto.getType() == Protos.Key.Type.ENCRYPTED_SCRYPT_AES)) {
        throw new IllegalArgumentException(
            "Unknown key type in wallet, type = " + keyProto.getType());
      }

      byte[] privKey = keyProto.hasPrivateKey() ? keyProto.getPrivateKey().toByteArray() : null;
      EncryptedPrivateKey encryptedPrivateKey = null;
      if (keyProto.hasEncryptedPrivateKey()) {
        Protos.EncryptedPrivateKey encryptedPrivateKeyProto = keyProto.getEncryptedPrivateKey();
        encryptedPrivateKey =
            new EncryptedPrivateKey(
                encryptedPrivateKeyProto.getInitialisationVector().toByteArray(),
                encryptedPrivateKeyProto.getEncryptedPrivateKey().toByteArray());
      }

      byte[] pubKey = keyProto.hasPublicKey() ? keyProto.getPublicKey().toByteArray() : null;

      ECKey ecKey;
      final KeyCrypter keyCrypter = wallet.getKeyCrypter();
      if (keyCrypter != null
          && keyCrypter.getUnderstoodEncryptionType() != EncryptionType.UNENCRYPTED) {
        // If the key is encrypted construct an ECKey using the encrypted private key bytes.
        ecKey = new ECKey(encryptedPrivateKey, pubKey, keyCrypter);
      } else {
        // Construct an unencrypted private key.
        ecKey = new ECKey(privKey, pubKey);
      }
      ecKey.setCreationTimeSeconds((keyProto.getCreationTimestamp() + 500) / 1000);
      wallet.addKey(ecKey);
    }

    // Read all transactions and insert into the txMap.
    for (Protos.Transaction txProto : walletProto.getTransactionList()) {
      readTransaction(txProto, wallet.getParams());
    }

    // Update transaction outputs to point to inputs that spend them
    for (Protos.Transaction txProto : walletProto.getTransactionList()) {
      WalletTransaction wtx = connectTransactionOutputs(txProto);
      wallet.addWalletTransaction(wtx);
    }

    // Update the lastBlockSeenHash.
    if (!walletProto.hasLastSeenBlockHash()) {
      wallet.setLastBlockSeenHash(null);
    } else {
      wallet.setLastBlockSeenHash(byteStringToHash(walletProto.getLastSeenBlockHash()));
    }
    if (!walletProto.hasLastSeenBlockHeight()) {
      wallet.setLastBlockSeenHeight(-1);
    } else {
      wallet.setLastBlockSeenHeight(walletProto.getLastSeenBlockHeight());
    }

    loadExtensions(wallet, walletProto);

    if (walletProto.hasVersion()) {
      wallet.setVersion(walletProto.getVersion());
    }

    // Make sure the object can be re-used to read another wallet without corruption.
    txMap.clear();
  }
예제 #5
0
  @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");
    }
  }