@Override
 public void deserializeWalletExtension(Wallet containingWallet, byte[] data) throws Exception {
   lock.lock();
   try {
     checkState(this.containingWallet == null || this.containingWallet == containingWallet);
     this.containingWallet = containingWallet;
     NetworkParameters params = containingWallet.getParams();
     ClientState.StoredClientPaymentChannels states =
         ClientState.StoredClientPaymentChannels.parseFrom(data);
     for (ClientState.StoredClientPaymentChannel storedState : states.getChannelsList()) {
       Transaction refundTransaction =
           params
               .getDefaultSerializer()
               .makeTransaction(storedState.getRefundTransaction().toByteArray());
       refundTransaction.getConfidence().setSource(TransactionConfidence.Source.SELF);
       ECKey myKey =
           (storedState.getMyKey().isEmpty())
               ? containingWallet.findKeyFromPubKey(storedState.getMyPublicKey().toByteArray())
               : ECKey.fromPrivate(storedState.getMyKey().toByteArray());
       StoredClientChannel channel =
           new StoredClientChannel(
               Sha256Hash.wrap(storedState.getId().toByteArray()),
               params
                   .getDefaultSerializer()
                   .makeTransaction(storedState.getContractTransaction().toByteArray()),
               refundTransaction,
               myKey,
               Coin.valueOf(storedState.getValueToMe()),
               Coin.valueOf(storedState.getRefundFees()),
               false);
       if (storedState.hasCloseTransactionHash()) {
         Sha256Hash closeTxHash =
             Sha256Hash.wrap(storedState.getCloseTransactionHash().toByteArray());
         channel.close = containingWallet.getTransaction(closeTxHash);
       }
       putChannel(channel, false);
     }
   } finally {
     lock.unlock();
   }
 }
  private void doMigrateFrom_v1_0_262(Context context, NetworkParameters migrationParams)
      throws IOException {
    Log.d(TAG, "********* MIGRATION FROM v1.0.262 - " + migrationParams.getId() + "*********");

    final File rootDir = context.getFilesDir();
    final File storageDir;
    final File archiveDir = new File(rootDir, "archive_" + System.currentTimeMillis());
    final File walletFile;
    final File chainFile;

    final File newWalletFile;
    final File newChainFile;

    if (ClientUtils.isMainNet(migrationParams)) {
      String walletFilesPrefix = AppConfig.MainNetConfig.get().getWalletFilesPrefix();
      storageDir = new File(rootDir, "mainnet_wallet__uuid_object_storage");
      walletFile = new File(rootDir, "mainnet_wallet_.wallet");
      newWalletFile = new File(rootDir, walletFilesPrefix + ".wallet");
      chainFile = new File(rootDir, "mainnet_wallet_.spvchain");
      newChainFile = new File(rootDir, walletFilesPrefix + ".spvchain");
    } else if (ClientUtils.isTestNet(migrationParams)) {
      String walletFilesPrefix = AppConfig.TestNetConfig.get().getWalletFilesPrefix();
      storageDir = new File(rootDir, "testnet_wallet__uuid_object_storage");
      walletFile = new File(rootDir, "testnet_wallet_.wallet");
      newWalletFile = new File(rootDir, walletFilesPrefix + ".wallet");
      chainFile = new File(rootDir, "testnet_wallet_.spvchain");
      newChainFile = new File(rootDir, walletFilesPrefix + ".spvchain");
    } else {
      throw new RuntimeException(
          "Network params not supported (unknown): " + migrationParams.toString());
    }

    final File keyFile = new File(storageDir, "ECKeyWrapper.json");

    if (keyFile.exists() && walletFile.exists()) {

      // Keys: stored in ECKeyWrapper.json
      /* Key format (JSON):
        {
          "...uuid1...": {
              "isPublicOnly": true,
              "keyPayload": [...bytes (integers)...],
              "name": "remote_server_public_key",
              "uuid": "...uuid1..."
          },
          "...uuid2...": {
              "isPublicOnly": false,
              "keyPayload": [...bytes (integers)...],
              "name": "remote_client_public_key",
              "uuid": "...uuid2..."
          }
        }
      */

      Log.d(TAG, "Key file found: " + keyFile);
      String keyFileJson = FileUtils.readFileToString(keyFile);
      Type type = new TypeToken<Map<String, ECKeyWrapper>>() {}.getType();
      // Note: do not use gson from serializeutils (key is not stored in base64).
      Map<String, ECKeyWrapper> keys = new Gson().fromJson(keyFileJson, type);
      ECKey serverKey = null;
      ECKey clientKey = null;
      for (ECKeyWrapper key : keys.values()) {
        if (key.isPublicOnly && key.name.equals("remote_server_public_key")) {
          serverKey = ECKey.fromPublicOnly(key.keyPayload);
        } else if (!key.isPublicOnly && key.name.equals("remote_client_public_key")) {
          clientKey = ECKey.fromPrivate(key.keyPayload);
        } else {
          Log.d(TAG, "Unknown key name: " + key.name);
        }
      }

      if (clientKey != null && serverKey != null) {
        Log.d(TAG, "Found client and server keys - store in shared preferences.");
        try {

          /** ******** Actual Migration Code ********* */
          SharedPrefUtils.setClientKey(context, migrationParams, clientKey);
          SharedPrefUtils.setServerKey(context, migrationParams, serverKey, "n/a - migration");
          Log.d(
              TAG,
              "Migrated keys:"
                  + " clientPubKey="
                  + clientKey.getPublicKeyAsHex()
                  + ", serverPubKey="
                  + serverKey.getPublicKeyAsHex());

          // move wallet file
          Log.d(
              TAG,
              "Migrate wallet file: " + walletFile.toString() + " -> " + newWalletFile.toString());
          FileUtils.copyFile(walletFile, newWalletFile);
          Log.d(
              TAG,
              "Migrate chain file: " + chainFile.toString() + " -> " + newChainFile.toString());
          FileUtils.copyFile(chainFile, newChainFile);

          SharedPrefUtils.enableMultisig2of2ToCltvForwarder(context);

          // move everything to an archive file.
          Log.d(TAG, "Move old files to archive dir: " + archiveDir.toString());
          FileUtils.moveToDirectory(storageDir, archiveDir, true);
          FileUtils.moveToDirectory(walletFile, archiveDir, true);
          FileUtils.moveToDirectory(chainFile, archiveDir, true);

        } catch (Exception e) {
          Log.d(TAG, "Exception: ", e);
          // clear the changes made.
          SharedPrefUtils.setClientKey(context, migrationParams, null);
          SharedPrefUtils.setServerKey(context, migrationParams, null, "");
          if (newWalletFile.exists()) {
            newWalletFile.delete();
          }
        }
      }
    } else {
      Log.d(
          TAG,
          "Key file or wallet file not found - no migration required - "
              + String.format(
                  "keyFile: %s (exists: %s), walletFile: %s (exists: %s)",
                  keyFile.toString(),
                  keyFile.exists(),
                  walletFile.toString(),
                  walletFile.exists()));
    }

    Log.d(TAG, "********* MIGRATION FROM v1.0.262 FINISHED *********");
  }
 @Override
 public ListenableFuture<ECKey.ECDSASignature> signHash(final Sha256Hash hash) {
   return Futures.immediateFuture(ECKey.fromPrivate(hdWallet.getPrivKey()).sign(hash));
 }