Example #1
0
  public List<Balance> getBalances() {
    if (mHDWallet == null) return null;

    List<Balance> balances = new LinkedList<Balance>();
    mHDWallet.getBalances(balances);
    return balances;
  }
Example #2
0
  public void rescanBlockchain(long rescanTime) {
    mLogger.info(String.format("RESCANNING from %d", rescanTime));

    // Make sure we are in a good state for this.
    if (mState != State.READY) {
      mLogger.warn("can't rescan until the wallet is ready");
      return;
    }

    switch (mSyncState) {
      case SYNCHRONIZED:
        mSyncState = SyncState.RESCAN;
        break;
      default:
        mSyncState = SyncState.RERESCAN;
        break;
    }

    // Remove our wallet event listener.
    mKit.wallet().removeEventListener(mWalletListener);

    // Persist and remove our HDWallet.
    //
    // NOTE - It's best not to clear the balances here.  When the
    // transactions are filling in on the transactions screen it's
    // disturbing to see negative historical balances.  They'll
    // get completely refigured when the sync is done anyway ...
    //
    mHDWallet.persist(mApp);
    mHDWallet = null;

    mLogger.info("resetting wallet state");
    mKit.wallet().clearTransactions(0);
    mKit.wallet().setLastBlockSeenHeight(-1); // magic value
    mKit.wallet().setLastBlockSeenHash(null);

    mLogger.info("shutting kit down");
    try {
      mKit.shutDown();
      mKit = null;
    } catch (Exception ex) {
      mLogger.error("kit shutdown failed: " + ex.toString());
      return;
    }

    File dir = mApp.getWalletDir();
    String spvpath = mApp.getWalletPrefix() + ".spvchain";
    mLogger.info("removing spvchain file " + dir + spvpath);
    File chainFile = new File(dir, spvpath);
    if (!chainFile.delete()) mLogger.error("delete of spvchain file failed");

    mLogger.info("restarting wallet");

    mKeyCrypter = mApp.mKeyCrypter;
    mAesKey = mApp.mAesKey;

    setState(State.SETUP);
    mTask = new SetupWalletTask();
    mTask.execute(rescanTime);
  }
Example #3
0
  public long computeRecommendedFee(int acctnum, long amount, boolean spendUnconfirmed)
      throws IllegalArgumentException, InsufficientMoneyException {

    mLogger.info("computeRecommendedFee starting");
    long fee = mHDWallet.computeRecommendedFee(mKit.wallet(), acctnum, amount, spendUnconfirmed);
    mLogger.info("computeRecommendedFee finished");
    return fee;
  }
Example #4
0
  public void changePasscode(KeyParameter oldAesKey, KeyCrypter keyCrypter, KeyParameter aesKey) {
    mLogger.info("changePasscode starting");

    // Change the parameters on our HDWallet.
    mHDWallet.setPersistCrypter(keyCrypter, aesKey);
    mHDWallet.persist(mApp);

    mLogger.info("persisted HD wallet");

    // Decrypt the wallet with the old key.
    mKit.wallet().decrypt(oldAesKey);

    mLogger.info("decrypted base wallet");

    // Encrypt the wallet using the new key.
    mKit.wallet().encrypt(keyCrypter, aesKey);

    mLogger.info("reencrypted base wallet");
  }
Example #5
0
        @Override
        public void onWalletChanged(Wallet wallet) {
          // Compute balances and transaction counts.
          Iterable<WalletTransaction> iwt = mKit.wallet().getWalletTransactions();
          mHDWallet.applyAllTransactions(iwt);

          // Check to make sure we have sufficient margins.
          int maxExtended = mHDWallet.ensureMargins(mKit.wallet());

          // Persist the new state.
          mHDWallet.persist(mApp);

          Intent intent = new Intent("wallet-state-changed");
          mLBM.sendBroadcast(intent);

          if (maxExtended > HDChain.maxSafeExtend()) {
            mLogger.info(String.format("%d addresses added, rescanning", maxExtended));
            rescanBlockchain(HDAddress.EPOCH);
          }
        }
Example #6
0
  public void sweepKey(ECKey key, long fee, int accountId, JSONArray outputs) {
    mLogger.info("sweepKey starting");

    mLogger.info("key addr " + key.toAddress(mParams).toString());

    Transaction tx = new Transaction(mParams);

    long balance = 0;
    ArrayList<Script> scripts = new ArrayList<Script>();
    try {
      for (int ii = 0; ii < outputs.length(); ++ii) {
        JSONObject output;
        output = outputs.getJSONObject(ii);

        String tx_hash = output.getString("tx_hash");
        int tx_output_n = output.getInt("tx_output_n");
        String script = output.getString("script");

        // Reverse byte order, create hash.
        Sha256Hash hash = new Sha256Hash(WalletUtil.msgHexToBytes(tx_hash));

        tx.addInput(
            new TransactionInput(
                mParams, tx, new byte[] {}, new TransactionOutPoint(mParams, tx_output_n, hash)));

        scripts.add(new Script(Hex.decode(script)));

        balance += output.getLong("value");
      }
    } catch (JSONException e) {
      e.printStackTrace();
      throw new RuntimeException("trouble parsing unspent outputs");
    }

    // Compute balance - fee.
    long amount = balance - fee;
    mLogger.info(String.format("sweeping %d", amount));

    // Figure out the destination address.
    Address to = mHDWallet.nextReceiveAddress(accountId);
    mLogger.info("sweeping to " + to.toString());

    // Add output.
    tx.addOutput(BigInteger.valueOf(amount), to);

    WalletUtil.signTransactionInputs(tx, Transaction.SigHash.ALL, key, scripts);

    mLogger.info("tx bytes: " + new String(Hex.encode(tx.bitcoinSerialize())));
    // mKit.peerGroup().broadcastTransaction(tx);
    broadcastTransaction(mKit.peerGroup(), tx);

    mLogger.info("sweepKey finished");
  }
Example #7
0
  public void addAccount() {
    mLogger.info("add account");

    // Make sure we are in a good state for this.
    if (mState != State.READY) {
      mLogger.warn("can't add an account until the wallet is ready");
      return;
    }

    mHDWallet.addAccount();
    mHDWallet.ensureMargins(mKit.wallet());

    // Set the new keys creation time to now.
    long now = Utils.now().getTime() / 1000;

    // Adding all the keys is overkill, but it is simpler for now.
    ArrayList<ECKey> keys = new ArrayList<ECKey>();
    mHDWallet.gatherAllKeys(now, keys);
    mLogger.info(String.format("adding %d keys", keys.size()));
    mKit.wallet().addKeys(keys);

    mHDWallet.persist(mApp);
  }
Example #8
0
  public void sendCoinsFromAccount(
      int acctnum, String address, long amount, long fee, boolean spendUnconfirmed)
      throws RuntimeException {

    if (mHDWallet == null) return;

    try {
      Address dest = new Address(mParams, address);

      mLogger.info(
          String.format(
              "send coins: acct=%d, dest=%s, val=%d, fee=%d", acctnum, address, amount, fee));

      mHDWallet.sendAccountCoins(mKit.wallet(), acctnum, dest, amount, fee, spendUnconfirmed);

    } catch (WrongNetworkException ex) {
      String msg = "Address for wrong network: " + ex.getMessage();
      throw new RuntimeException(msg);
    } catch (AddressFormatException ex) {
      String msg = "Malformed bitcoin address: " + ex.getMessage();
      throw new RuntimeException(msg);
    }
  }
Example #9
0
 public long balanceForAccount(int acctnum) {
   return mHDWallet.balanceForAccount(acctnum);
 }
Example #10
0
 public HDAddressDescription findAddress(Address addr) {
   return mHDWallet.findAddress(addr);
 }
Example #11
0
 public byte[] getWalletSeed() {
   return mHDWallet == null ? null : mHDWallet.getWalletSeed();
 }
Example #12
0
 public void persist() {
   mHDWallet.persist(mApp);
 }
Example #13
0
    @Override
    protected Integer doInBackground(Long... params) {
      // scanTime  0 : full rescan
      // scanTime  t : scan from time t
      final Long scanTime = params[0];

      setState(State.WALLET_SETUP);

      mLogger.info("setting up wallet, scanTime=" + scanTime.toString());

      mLogger.info("getting network parameters");

      mParams = Constants.getNetworkParameters(getApplicationContext());

      // Try to restore existing wallet.
      mHDWallet = null;
      try {
        mHDWallet = HDWallet.restore(mApp, mParams, mKeyCrypter, mAesKey);
      } catch (InvalidCipherTextException ex) {
        mLogger.error("wallet restore failed: " + ex.toString());
      } catch (IOException ex) {
        mLogger.error("wallet restore failed: " + ex.toString());
      } catch (RuntimeException ex) {
        mLogger.error("wallet restore failed: " + ex.toString());
      }

      if (mHDWallet == null) {

        mLogger.error("WalletService started with bad HDWallet");
        System.exit(0);
      }

      mLogger.info("creating new wallet app kit");

      // Checkpointing fails on full rescan because the earliest
      // create time is earlier than the genesis block time.
      //
      InputStream chkpntis = null;
      if (scanTime != 0) {
        try {
          chkpntis = getAssets().open(Constants.CHECKPOINTS_FILENAME);
        } catch (IOException e) {
          chkpntis = null;
        }
      }

      mKit =
          new MyWalletAppKit(
              mParams, mApp.getWalletDir(), mApp.getWalletPrefix(), mKeyCrypter, scanTime) {
            @Override
            protected void onSetupCompleted() {
              mLogger.info("adding keys");

              setState(WalletService.State.KEYS_ADD);

              // Add all the existing keys, they'll be
              // ignored if they are already in the
              // WalletAppKit.
              //
              ArrayList<ECKey> keys = new ArrayList<ECKey>();
              mHDWallet.gatherAllKeys(HDAddress.EPOCH, keys);
              mLogger.info(String.format("adding %d keys", keys.size()));
              wallet().addKeys(keys);

              // Do we have enough margin on all our chains?
              // Add keys to chains which don't have enough
              // unused addresses at the end.
              //
              mHDWallet.ensureMargins(wallet());

              peerGroup()
                  .setFastCatchupTimeSecs(
                      (scanTime == 0 ? mParams.getGenesisBlock().getTimeSeconds() : scanTime));

              if (mPrefs.getBoolean("pref_reduceBloomFalsePositives", false)) {
                mLogger.info("reducing bloom false positives");
                peerGroup().setBloomFilterFalsePositiveRate(0.000001);
              }

              // We don't need to check for HDChain.maxSafeExtend()
              // here because we are about to scan anyway.
              // We'll check again after the scan ...

              // Now we're peering.
              setState(WalletService.State.PEERING);
            }
          };
      mKit.setDownloadListener(mkDownloadListener());
      if (chkpntis != null) mKit.setCheckpoints(chkpntis);

      setState(State.WALLET_SETUP);

      mLogger.info("waiting for blockchain setup");

      // Download the block chain and wait until it's done.
      mKit.startAndWait();

      mLogger.info("blockchain setup finished, state = " + getStateString());

      // Bail if we're being shutdown ...
      if (mState == State.SHUTDOWN) {
        mHDWallet.persist(mApp);
        return null;
      }

      mBalanceAvailable = mKit.wallet().getBalance(BalanceType.AVAILABLE);
      mBalanceEstimated = mKit.wallet().getBalance(BalanceType.ESTIMATED);

      mLogger.info("avail balance = " + mBalanceAvailable.toString());
      mLogger.info("estim balance = " + mBalanceEstimated.toString());

      // Compute balances and transaction counts.
      Iterable<WalletTransaction> iwt = mKit.wallet().getWalletTransactions();
      mHDWallet.applyAllTransactions(iwt);

      // Check the margins again, since transactions may have arrived.
      int maxExtended = mHDWallet.ensureMargins(mKit.wallet());

      // Persist the new state.
      mHDWallet.persist(mApp);

      // Listen for future wallet changes.
      mKit.wallet().addEventListener(mWalletListener);

      setState(State.READY); // This may be temporary ...

      return maxExtended;
    }
Example #14
0
 public long availableForAccount(int acctnum) {
   return mHDWallet.availableForAccount(acctnum);
 }
Example #15
0
 public List<HDAccount> getAccounts() {
   if (mHDWallet == null) return null;
   return mHDWallet.getAccounts();
 }
Example #16
0
 public HDAccount getAccount(int accountId) {
   if (mHDWallet == null) return null;
   return mHDWallet.getAccount(accountId);
 }
Example #17
0
 public String getPairingCode() {
   JSONObject obj = mHDWallet.dumps(true);
   return obj.toString();
 }
Example #18
0
 public Address nextReceiveAddress(int acctnum) {
   return mHDWallet.nextReceiveAddress(acctnum);
 }
Example #19
0
 public String getFormatVersionString() {
   return mHDWallet.getFormatVersionString();
 }
Example #20
0
 public AmountAndFee useAll(int acctnum, boolean spendUnconfirmed)
     throws InsufficientMoneyException {
   return mHDWallet.useAll(mKit.wallet(), acctnum, spendUnconfirmed);
 }
Example #21
0
 public HDWallet.HDStructVersion getHDStructVersion() {
   return mHDWallet.getHDStructVersion();
 }
Example #22
0
 public MnemonicCodeX.Version getBIP39Version() {
   return mHDWallet.getBIP39Version();
 }
Example #23
0
 public long amountForAccount(WalletTransaction wtx, int acctnum) {
   return mHDWallet.amountForAccount(wtx, acctnum);
 }