private WalletTransaction connectTransactionOutputs(
      org.bitcoinj.wallet.Protos.Transaction txProto) throws UnreadableWalletException {
    Transaction tx = txMap.get(txProto.getHash());
    final WalletTransaction.Pool pool;
    switch (txProto.getPool()) {
      case DEAD:
        pool = WalletTransaction.Pool.DEAD;
        break;
      case PENDING:
        pool = WalletTransaction.Pool.PENDING;
        break;
      case SPENT:
        pool = WalletTransaction.Pool.SPENT;
        break;
      case UNSPENT:
        pool = WalletTransaction.Pool.UNSPENT;
        break;
        // Upgrade old wallets: inactive pool has been merged with the pending pool.
        // Remove this some time after 0.9 is old and everyone has upgraded.
        // There should not be any spent outputs in this tx as old wallets would not allow them to
        // be spent
        // in this state.
      case INACTIVE:
      case PENDING_INACTIVE:
        pool = WalletTransaction.Pool.PENDING;
        break;
      default:
        throw new UnreadableWalletException("Unknown transaction pool: " + txProto.getPool());
    }
    for (int i = 0; i < tx.getOutputs().size(); i++) {
      TransactionOutput output = tx.getOutputs().get(i);
      final Protos.TransactionOutput transactionOutput = txProto.getTransactionOutput(i);
      if (transactionOutput.hasSpentByTransactionHash()) {
        final ByteString spentByTransactionHash = transactionOutput.getSpentByTransactionHash();
        Transaction spendingTx = txMap.get(spentByTransactionHash);
        if (spendingTx == null) {
          throw new UnreadableWalletException(
              String.format(
                  "Could not connect %s to %s",
                  tx.getHashAsString(), byteStringToHash(spentByTransactionHash)));
        }
        final int spendingIndex = transactionOutput.getSpentByTransactionIndex();
        TransactionInput input = checkNotNull(spendingTx.getInput(spendingIndex));
        input.connect(output);
      }
    }

    if (txProto.hasConfidence()) {
      Protos.TransactionConfidence confidenceProto = txProto.getConfidence();
      TransactionConfidence confidence = tx.getConfidence();
      readConfidence(tx, confidenceProto, confidence);
    }

    return new WalletTransaction(pool, tx);
  }
 /**
  * Connects this input to the relevant output of the referenced transaction. Connecting means
  * updating the internal pointers and spent flags. If the mode is to ABORT_ON_CONFLICT then the
  * spent output won't be changed, but the outpoint.fromTx pointer will still be updated.
  *
  * @param transaction The transaction to try.
  * @param mode Whether to abort if there's a pre-existing connection or not.
  * @return NO_SUCH_TX if transaction is not the prevtx, ALREADY_SPENT if there was a conflict,
  *     SUCCESS if not.
  */
 public ConnectionResult connect(Transaction transaction, ConnectMode mode) {
   if (!transaction.getHash().equals(outpoint.getHash())) return ConnectionResult.NO_SUCH_TX;
   checkElementIndex(
       (int) outpoint.getIndex(), transaction.getOutputs().size(), "Corrupt transaction");
   TransactionOutput out = transaction.getOutput((int) outpoint.getIndex());
   if (!out.isAvailableForSpending()) {
     if (getParentTransaction().equals(outpoint.fromTx)) {
       // Already connected.
       return ConnectionResult.SUCCESS;
     } else if (mode == ConnectMode.DISCONNECT_ON_CONFLICT) {
       out.markAsUnspent();
     } else if (mode == ConnectMode.ABORT_ON_CONFLICT) {
       outpoint.fromTx = out.getParentTransaction();
       return TransactionInput.ConnectionResult.ALREADY_SPENT;
     }
   }
   connect(out);
   return TransactionInput.ConnectionResult.SUCCESS;
 }