private void watchCloseConfirmations() {
    // When we see the close transaction get a few confirmations, we can just delete the record
    // of this channel along with the refund tx from the wallet, because we're not going to need
    // any of that any more.
    final TransactionConfidence confidence = storedChannel.close.getConfidence();
    ListenableFuture<Transaction> future =
        confidence.getDepthFuture(CONFIRMATIONS_FOR_DELETE, Threading.SAME_THREAD);
    Futures.addCallback(
        future,
        new FutureCallback<Transaction>() {
          @Override
          public void onSuccess(Transaction result) {
            deleteChannelFromWallet();
          }

          @Override
          public void onFailure(Throwable t) {
            Throwables.propagate(t);
          }
        });
  }
 private void readConfidence(
     Transaction tx,
     Protos.TransactionConfidence confidenceProto,
     TransactionConfidence confidence) {
   // We are lenient here because tx confidence is not an essential part of the wallet.
   // If the tx has an unknown type of confidence, ignore.
   if (!confidenceProto.hasType()) {
     log.warn("Unknown confidence type for tx {}", tx.getHashAsString());
     return;
   }
   ConfidenceType confidenceType;
   switch (confidenceProto.getType()) {
     case BUILDING:
       confidenceType = ConfidenceType.BUILDING;
       break;
     case DEAD:
       confidenceType = ConfidenceType.DEAD;
       break;
       // These two are equivalent (must be able to read old wallets).
     case NOT_IN_BEST_CHAIN:
       confidenceType = ConfidenceType.PENDING;
       break;
     case NOT_SEEN_IN_CHAIN:
       confidenceType = ConfidenceType.PENDING;
       break;
     case UNKNOWN:
       // Fall through.
     default:
       confidenceType = ConfidenceType.UNKNOWN;
       break;
   }
   confidence.setConfidenceType(confidenceType);
   if (confidenceProto.hasAppearedAtHeight()) {
     if (confidence.getConfidenceType() != ConfidenceType.BUILDING) {
       log.warn("Have appearedAtHeight but not BUILDING for tx {}", tx.getHashAsString());
       return;
     }
     confidence.setAppearedAtChainHeight(confidenceProto.getAppearedAtHeight());
   }
   if (confidenceProto.hasDepth()) {
     if (confidence.getConfidenceType() != ConfidenceType.BUILDING) {
       log.warn("Have depth but not BUILDING for tx {}", tx.getHashAsString());
       return;
     }
     confidence.setDepthInBlocks(confidenceProto.getDepth());
   }
   if (confidenceProto.hasWorkDone()) {
     if (confidence.getConfidenceType() != ConfidenceType.BUILDING) {
       log.warn("Have workDone but not BUILDING for tx {}", tx.getHashAsString());
       return;
     }
     confidence.setWorkDone(BigInteger.valueOf(confidenceProto.getWorkDone()));
   }
   if (confidenceProto.hasOverridingTransaction()) {
     if (confidence.getConfidenceType() != ConfidenceType.DEAD) {
       log.warn("Have overridingTransaction but not OVERRIDDEN for tx {}", tx.getHashAsString());
       return;
     }
     Transaction overridingTransaction = txMap.get(confidenceProto.getOverridingTransaction());
     if (overridingTransaction == null) {
       log.warn(
           "Have overridingTransaction that is not in wallet for tx {}", tx.getHashAsString());
       return;
     }
     confidence.setOverridingTransaction(overridingTransaction);
   }
   for (Protos.PeerAddress proto : confidenceProto.getBroadcastByList()) {
     InetAddress ip;
     try {
       ip = InetAddress.getByAddress(proto.getIpAddress().toByteArray());
     } catch (UnknownHostException e) {
       throw new RuntimeException(e); // IP address is of invalid length.
     }
     int port = proto.getPort();
     PeerAddress address = new PeerAddress(ip, port);
     address.setServices(BigInteger.valueOf(proto.getServices()));
     confidence.markBroadcastBy(address);
   }
   switch (confidenceProto.getSource()) {
     case SOURCE_SELF:
       confidence.setSource(TransactionConfidence.Source.SELF);
       break;
     case SOURCE_NETWORK:
       confidence.setSource(TransactionConfidence.Source.NETWORK);
       break;
     case SOURCE_UNKNOWN:
       // Fall through.
     default:
       confidence.setSource(TransactionConfidence.Source.UNKNOWN);
       break;
   }
 }
Exemple #3
0
        @Override
        public void onCoinsSent(
            Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) {
          BigInteger amt = prevBalance.subtract(newBalance);
          final long amount = amt.longValue();

          WalletApplication app = (WalletApplication) getApplicationContext();
          final BTCFmt btcfmt = app.getBTCFmt();

          // We allocate a new notification id for each receive.
          // We use it on both the receive and confirm so it
          // will replace the receive note with the confirm ...
          final int noteId = ++mNoteId;

          mLogger.info(String.format("showing notification send %d", amount));

          showEventNotification(
              noteId,
              R.drawable.ic_note_bc_red_lt,
              mRes.getString(R.string.wallet_service_note_sent_title, btcfmt.unitStr()),
              mRes.getString(
                  R.string.wallet_service_note_sent_msg, btcfmt.format(amount), btcfmt.unitStr()));

          final TransactionConfidence txconf = tx.getConfidence();

          final TransactionConfidence.Listener listener =
              new TransactionConfidence.Listener() {
                @Override
                public void onConfidenceChanged(Transaction tx, ChangeReason reason) {
                  // Wait until it's not pending anymore.
                  if (tx.isPending()) return;

                  ConfidenceType ct = tx.getConfidence().getConfidenceType();

                  if (ct == ConfidenceType.BUILDING) {
                    mLogger.info(String.format("send %d confirm", amount));

                    // Show no longer pending.
                    showEventNotification(
                        noteId,
                        R.drawable.ic_note_bc_red,
                        mRes.getString(R.string.wallet_service_note_scnf_title, btcfmt.unitStr()),
                        mRes.getString(
                            R.string.wallet_service_note_scnf_msg,
                            btcfmt.format(amount),
                            btcfmt.unitStr()));
                  } else if (ct == ConfidenceType.DEAD) {
                    mLogger.info(String.format("send %d dead", amount));
                    // Notify dead.
                    showEventNotification(
                        noteId,
                        R.drawable.ic_note_bc_gray,
                        mRes.getString(R.string.wallet_service_note_sdead_title, btcfmt.unitStr()),
                        mRes.getString(
                            R.string.wallet_service_note_sdead_msg,
                            btcfmt.format(amount),
                            btcfmt.unitStr()));

                  } else {
                    mLogger.info(String.format("send %d unknown", amount));
                  }

                  // We're all done listening ...
                  txconf.removeEventListener(this);
                }
              };

          txconf.addEventListener(listener);
        }
  private static void writeConfidence(
      Protos.Transaction.Builder txBuilder,
      TransactionConfidence confidence,
      Protos.TransactionConfidence.Builder confidenceBuilder) {
    synchronized (confidence) {
      confidenceBuilder.setType(
          Protos.TransactionConfidence.Type.valueOf(confidence.getConfidenceType().getValue()));
      if (confidence.getConfidenceType() == ConfidenceType.BUILDING) {
        confidenceBuilder.setAppearedAtHeight(confidence.getAppearedAtChainHeight());
        confidenceBuilder.setDepth(confidence.getDepthInBlocks());
        if (confidence.getWorkDone() != null) {
          confidenceBuilder.setWorkDone(confidence.getWorkDone().longValue());
        }
      }
      if (confidence.getConfidenceType() == ConfidenceType.DEAD) {
        // Copy in the overriding transaction, if available.
        // (A dead coinbase transaction has no overriding transaction).
        if (confidence.getOverridingTransaction() != null) {
          Sha256Hash overridingHash = confidence.getOverridingTransaction().getHash();
          confidenceBuilder.setOverridingTransaction(hashToByteString(overridingHash));
        }
      }
      TransactionConfidence.Source source = confidence.getSource();
      switch (source) {
        case SELF:
          confidenceBuilder.setSource(Protos.TransactionConfidence.Source.SOURCE_SELF);
          break;
        case NETWORK:
          confidenceBuilder.setSource(Protos.TransactionConfidence.Source.SOURCE_NETWORK);
          break;
        case UNKNOWN:
          // Fall through.
        default:
          confidenceBuilder.setSource(Protos.TransactionConfidence.Source.SOURCE_UNKNOWN);
          break;
      }
    }

    for (ListIterator<PeerAddress> it = confidence.getBroadcastBy(); it.hasNext(); ) {
      PeerAddress address = it.next();
      Protos.PeerAddress proto =
          Protos.PeerAddress.newBuilder()
              .setIpAddress(ByteString.copyFrom(address.getAddr().getAddress()))
              .setPort(address.getPort())
              .setServices(address.getServices().longValue())
              .build();
      confidenceBuilder.addBroadcastBy(proto);
    }
    txBuilder.setConfidence(confidenceBuilder);
  }