/** * If the transactions outputs are all marked as spent, and it's in the unspent map, move it. * If the owned transactions outputs are not all marked as spent, and it's in the spent map, move it. */ private void maybeMovePool(Transaction tx, String context) { checkState(lock.isHeldByCurrentThread()); if (tx.isEveryOwnedOutputSpent(this)) { // There's nothing left I can spend in this transaction. if (unspent.remove(tx.getHash()) != null) { if (log.isInfoEnabled()) { log.info(" {} {} <-unspent ->spent", tx.getHashAsString(), context); } spent.put(tx.getHash(), tx); } } else { if (spent.remove(tx.getHash()) != null) { if (log.isInfoEnabled()) { log.info(" {} {} <-spent ->unspent", tx.getHashAsString(), context); } unspent.put(tx.getHash(), tx); } } }
@Override public void onCoinsReceived(final Wallet wallet, final Transaction tx, final Coin prevBalance, final Coin newBalance) { transactionsReceived.incrementAndGet(); final int bestChainHeight = blockChain.getBestChainHeight(); final Address address = WalletUtils.getWalletAddressOfReceived(tx, wallet); final Coin amount = tx.getValue(wallet); final ConfidenceType confidenceType = tx.getConfidence().getConfidenceType(); final Sha256Hash hash = tx.getHash(); handler.post(new Runnable() { @Override public void run() { final boolean isReceived = amount.signum() > 0; final boolean replaying = bestChainHeight < config.getBestChainHeightEver(); final boolean isReplayedTx = confidenceType == ConfidenceType.BUILDING && replaying; if (isReceived && !isReplayedTx) notifyCoinsReceived(address, amount, hash); } }); }
@Override public void onBindViewHolder(ViewHolder holder, int position) { // - get element from your dataset at this position // - replace the contents of the view with that element holder.mTvTitle.setText(""); synchronized (mDataset) { try { final Transaction tx = mDataset.get(position); holder.mTvTitle.setText(String.valueOf(tx.getOutputSum().getValue()/100000000) + " BTC"+((tx.isPending())?" (U)":"")); holder.mTvHash.setText(tx.getHashAsString()); holder.key = tx.getHashAsString().toString(); }catch (Exception e){ e.printStackTrace(); } } }
/** * This method is used by a {@link Peer} to find out if a transaction that has been announced is interesting, * that is, whether we should bother downloading its dependencies and exploring the transaction to decide how * risky it is. If this method returns true then {@link Wallet#receivePending(Transaction, java.util.List)} * will soon be called with the transactions dependencies as well. */ public boolean isPendingTransactionRelevant(Transaction tx) throws ScriptException { lock.lock(); try { // Ignore it if we already know about this transaction. Receiving a pending transaction never moves it // between pools. EnumSet<Pool> containingPools = getContainingPools(tx); if (!containingPools.equals(EnumSet.noneOf(Pool.class))) { log.debug("Received tx we already saw in a block or created ourselves: " + tx.getHashAsString()); return false; } // We only care about transactions that: // - Send us coins // - Spend our coins // - Double spend a tx in our wallet if (!isTransactionRelevant(tx)) { log.debug("Received tx that isn't relevant to this wallet, discarding."); return false; } return true; } finally { lock.unlock(); } }
/** * Return true if the transaction in input is a valid imprinting transaction and contains the specified address in * one of its output, otherwise false. * @param tx the transaction to check if is valid imprinting * @param networkParameters the {@link NetworkParameters} * @param imprintingAddress the address to check for * @return true if it's an imprinting transaction otherwise false */ public static boolean isValidImprintingTransaction(Transaction tx, NetworkParameters networkParameters, Address imprintingAddress) { // Retrieve sender String sender = tx.getInput(0).getFromAddress().toBase58(); // Check output List<TransactionOutput> transactionOutputs = tx.getOutputs(); for (TransactionOutput to : transactionOutputs) { Address address = to.getAddressFromP2PKHScript(networkParameters); if (address != null && address.equals(imprintingAddress)) { return true; } } return false; }
@Override public List<Transaction> loadInBackground() { org.bitcoinj.core.Context.propagate(Constants.CONTEXT); final Set<Transaction> transactions = wallet.getTransactions(true); final List<Transaction> filteredTransactions = new ArrayList<Transaction>(transactions.size()); for (final Transaction tx : transactions) { final boolean sent = tx.getValue(wallet).signum() < 0; final boolean isInternal = tx.getPurpose() == Purpose.KEY_ROTATION; if ((direction == Direction.RECEIVED && !sent && !isInternal) || direction == null || (direction == Direction.SENT && sent && !isInternal)) filteredTransactions.add(tx); } Collections.sort(filteredTransactions, TRANSACTION_COMPARATOR); return filteredTransactions; }
private Result analyzeIsStandard() { // The IsStandard rules don't apply on testnet, because they're just a safety mechanism and we don't want to // crush innovation with valueless test coins. if (wallet != null && !wallet.getNetworkParameters().getId().equals(NetworkParameters.ID_MAINNET)) return Result.OK; RuleViolation ruleViolation = isStandard(tx); if (ruleViolation != RuleViolation.NONE) { nonStandard = tx; return Result.NON_STANDARD; } for (Transaction dep : dependencies) { ruleViolation = isStandard(dep); if (ruleViolation != RuleViolation.NONE) { nonStandard = dep; return Result.NON_STANDARD; } } return Result.OK; }
EnumSet<Pool> getContainingPools(Transaction tx) { lock.lock(); try { EnumSet<Pool> result = EnumSet.noneOf(Pool.class); Sha256Hash txHash = tx.getHash(); if (unspent.containsKey(txHash)) { result.add(Pool.UNSPENT); } if (spent.containsKey(txHash)) { result.add(Pool.SPENT); } if (pending.containsKey(txHash)) { result.add(Pool.PENDING); } if (dead.containsKey(txHash)) { result.add(Pool.DEAD); } return result; } finally { lock.unlock(); } }
@Nullable public static Address getWalletAddressOfReceived(final Transaction tx, final Wallet wallet) { for (final TransactionOutput output : tx.getOutputs()) { try { if (output.isMine(wallet)) { final Script script = output.getScriptPubKey(); return script.getToAddress(Constants.NETWORK_PARAMETERS, true); } } catch (final ScriptException x) { // swallow } } return null; }
/** * Called by the {@link BlockChain} when we receive a new filtered block that contains a transactions previously * received by a call to {@link #receivePending}.<p> * * This is necessary for the internal book-keeping Wallet does. When a transaction is received that sends us * coins it is added to a pool so we can use it later to create spends. When a transaction is received that * consumes outputs they are marked as spent so they won't be used in future.<p> * * A transaction that spends our own coins can be received either because a spend we created was accepted by the * network and thus made it into a block, or because our keys are being shared between multiple instances and * some other node spent the coins instead. We still have to know about that to avoid accidentally trying to * double spend.<p> * * A transaction may be received multiple times if is included into blocks in parallel chains. The blockType * parameter describes whether the containing block is on the main/best chain or whether it's on a presently * inactive side chain. We must still record these transactions and the blocks they appear in because a future * block might change which chain is best causing a reorganize. A re-org can totally change our balance! */ @Override public boolean notifyTransactionIsInBlock(Sha256Hash txHash, StoredBlock block, BlockChain.NewBlockType blockType, int relativityOffset) throws VerificationException { lock.lock(); try { Transaction tx = transactions.get(txHash); if (tx == null) { tx = riskDropped.get(txHash); if (tx != null) { // If this happens our risk analysis is probably wrong and should be improved. log.info("Risk analysis dropped tx {} but was included in block anyway", tx.getHash()); } else { // False positive that was broadcast to us and ignored by us because it was irrelevant to our keys. return false; } } receive(tx, block, blockType, relativityOffset); return true; } finally { lock.unlock(); } }
/** * Returns an list of N transactions, ordered by increasing age. Transactions on side chains are not included. * Dead transactions (overridden by double spends) are optionally included. <p> * <p/> * Note: the current implementation is O(num transactions in wallet). Regardless of how many transactions are * requested, the cost is always the same. In future, requesting smaller numbers of transactions may be faster * depending on how the wallet is implemented (eg if backed by a database). */ public List<Transaction> getRecentTransactions(int numTransactions, boolean includeDead) { lock.lock(); try { checkArgument(numTransactions >= 0); // Firstly, put all transactions into an array. int size = unspent.size() + spent.size() + pending.size(); if (numTransactions > size || numTransactions == 0) { numTransactions = size; } ArrayList<Transaction> all = new ArrayList<>(getTransactions(includeDead)); // Order by update time. Collections.sort(all, Transaction.SORT_TX_BY_UPDATE_TIME); if (numTransactions == all.size()) { return all; } else { all.subList(numTransactions, all.size()).clear(); return all; } } finally { lock.unlock(); } }
public void generateGenesisTransaction(int lockTime) { Transaction genesisTx; try { //generate genesis transaction if our proof is empty if(pm.getValidationPath().size() == 0 && wallet.getBalance(BalanceType.AVAILABLE).isGreaterThan(PSNYMVALUE)) { genesisTx = tg.generateGenesisTransaction(pm, walletFile, lockTime); //TODO register listener before sending tx out, to avoid missing a confidence change genesisTx.getConfidence().addEventListener(new Listener() { @Override public void onConfidenceChanged(TransactionConfidence arg0, ChangeReason arg1) { if (arg0.getConfidenceType() != TransactionConfidence.ConfidenceType.BUILDING) { return; } if(arg0.getDepthInBlocks() == 1) { //enough confidence, write proof message to the file system System.out.println("depth of genesis tx is now 1, consider ready for usage"); } } }); } } catch (InsufficientMoneyException e) { e.printStackTrace(); } }
/** * Marks all keys used in the transaction output as used in the wallet. * See {@link org.bitcoinj.wallet.DeterministicKeyChain#markKeyAsUsed(DeterministicKey)} for more info on this. */ private void markKeysAsUsed(Transaction tx) { keyChainGroupLock.lock(); try { for (TransactionOutput o : tx.getOutputs()) { try { Script script = o.getScriptPubKey(); if (script.isSentToRawPubKey()) { byte[] pubkey = script.getPubKey(); keyChainGroup.markPubKeyAsUsed(pubkey); } else if (script.isSentToAddress()) { byte[] pubkeyHash = script.getPubKeyHash(); keyChainGroup.markPubKeyHashAsUsed(pubkeyHash); } else if (script.isPayToScriptHash()) { Address a = Address.fromP2SHScript(tx.getParams(), script); keyChainGroup.markP2SHAddressAsUsed(a); } } catch (ScriptException e) { // Just means we didn't understand the output of this transaction: ignore it. log.warn("Could not parse tx output script: {}", e.toString()); } } } finally { keyChainGroupLock.unlock(); } }
@Override public void onBlocksDownloaded(Peer arg0, Block arg1, @Nullable FilteredBlock arg2, int arg3) { System.out.println("received block"); boolean receivedBcastAnnouncmnt = false; Map<Sha256Hash, Transaction> assocTxs = arg2.getAssociatedTransactions(); for(Transaction tx : assocTxs.values()) { System.out.println("from within mixpartner discovery " + tx); if(tx.getOutputs().size() > 1 && BroadcastAnnouncement.isBroadcastAnnouncementScript(tx.getOutput(1).getScriptBytes())) //&& !wallet.isTransactionRelevant(tx)) { //tx.getInput(0).getScriptSig().getChunks().get(0) { if(!this.broadcasts.contains(tx) && wallet.getTransaction(tx.getHash()) == null) { this.broadcasts.add(tx); receivedBcastAnnouncmnt = true; } } } if(receivedBcastAnnouncmnt) { for(BroadcastAnnouncementChangeEventListener l : listeners) { l.onBroadcastAnnouncementChanged(); } } }
private void initStateFromBitcoinUri(final Uri bitcoinUri) { final String input = bitcoinUri.toString(); new StringInputParser(input) { @Override protected void handlePaymentIntent(final PaymentIntent paymentIntent) { updateStateFrom(paymentIntent); } @Override protected void handlePrivateKey(final VersionedChecksummedBytes key) { throw new UnsupportedOperationException(); } @Override protected void handleDirectTransaction(final Transaction transaction) throws VerificationException { throw new UnsupportedOperationException(); } @Override protected void error(final int messageResId, final Object... messageArgs) { dialog(activity, activityDismissListener, 0, messageResId, messageArgs); } }.parse(); }
private void createTransientState() { ignoreNextNewBlock = new HashSet<>(); txConfidenceListener = new TransactionConfidence.Listener() { @Override public void onConfidenceChanged(TransactionConfidence confidence, TransactionConfidence.Listener.ChangeReason reason) { // This will run on the user code thread so we shouldn't do anything too complicated here. // We only want to queue a wallet changed event and auto-save if the number of peers announcing // the transaction has changed, as that confidence change is made by the networking code which // doesn't necessarily know at that point which wallets contain which transactions, so it's up // to us to listen for that. Other types of confidence changes (type, etc) are triggered by us, // so we'll queue up a wallet change event in other parts of the code. if (reason == ChangeReason.SEEN_PEERS) { lock.lock(); try { checkBalanceFuturesLocked(null); Transaction tx = getTransaction(confidence.getTransactionHash()); queueOnTransactionConfidenceChanged(tx); maybeQueueOnWalletChanged(); } finally { lock.unlock(); } } } }; acceptRiskyTransactions = false; }
private static @Nullable TransactionOutput findSpendableOutput(final Wallet wallet, final Transaction transaction, final Coin minimumOutputValue) { for (final TransactionOutput output : transaction.getOutputs()) { if (output.isMine(wallet) && output.isAvailableForSpending() && output.getValue().isGreaterThan(minimumOutputValue)) return output; } return null; }
/** Updates the table that contains Transaction Hashes */ public void update(){ DefaultTableModel model = (DefaultTableModel) table.getModel(); for (Transaction t : fullBlock.getTransactions()) { Object[] row = {t.getHashAsString()}; model.addRow(row); } }
/** Finds if tx is NOT spending other txns which are in the specified confidence type */ private boolean isNotSpendingTxnsInConfidenceType(Transaction tx, ConfidenceType confidenceType) { for (TransactionInput txInput : tx.getInputs()) { Transaction connectedTx = this.getTransaction(txInput.getOutpoint().getHash()); if (connectedTx != null && connectedTx.getConfidence().getConfidenceType().equals(confidenceType)) { return false; } } return true; }
/** * <p>Returns true if the given transaction sends coins to any of our keys, or has inputs spending any of our outputs, * and also returns true if tx has inputs that are spending outputs which are * not ours but which are spent by pending transactions.</p> * * <p>Note that if the tx has inputs containing one of our keys, but the connected transaction is not in the wallet, * it will not be considered relevant.</p> */ public boolean isTransactionRelevant(Transaction tx) throws ScriptException { lock.lock(); try { return tx.getValueSentFromMe(this).signum() > 0 || tx.getValueSentToMe(this).signum() > 0 || !findDoubleSpendsAgainst(tx, transactions).isEmpty(); } finally { lock.unlock(); } }
/** * Add a transaction to the tracked list. The TransactionList automatically adds itself as a confidence listener * at this transaction * @param transaction to be added to the list */ void add(Transaction transaction) { logger.debug("Adding tx %s to TransactionList", transaction.getHashAsString()); Sha256Hash txHash = transaction.getHash(); Transaction prevValue = transactions.put(txHash, transaction); if (null != prevValue) prevValue.getConfidence().removeEventListener(this); transaction.getConfidence().addEventListener(this); logger.debug("This list has now %d transactions", transactions.size()); informStateListenersTransactionsChanged(getTransactions()); }
/** Finds whether txA spends txB */ boolean spends(Transaction txA, Transaction txB) { for (TransactionInput txInput : txA.getInputs()) { if (txInput.getOutpoint().getHash().equals(txB.getHash())) { return true; } } return false; }
@Override public void onActivityResult(final int requestCode, final int resultCode, final Intent intent) { if (requestCode == REQUEST_CODE_SCAN) { if (resultCode == Activity.RESULT_OK) { final String input = intent.getStringExtra(ScanActivity.INTENT_EXTRA_RESULT); new StringInputParser(input) { @Override protected void handlePrivateKey(final VersionedChecksummedBytes key) { privateKeyToSweep = key; setState(State.DECODE_KEY); maybeDecodeKey(); } @Override protected void handlePaymentIntent(final PaymentIntent paymentIntent) { cannotClassify(input); } @Override protected void handleDirectTransaction(final Transaction transaction) throws VerificationException { cannotClassify(input); } @Override protected void error(final int messageResId, final Object... messageArgs) { dialog(activity, null, R.string.button_scan, messageResId, messageArgs); } }.parse(); } } }
/** * A List of Transactions with their state. * @return A Transactions Object as used in the swagger REST api */ public Transactions getTransactions() { Transactions txes = new Transactions(); for (Map.Entry<Sha256Hash, Transaction> element : transactions.entrySet()) { TransactionsInner transactionsInner = new TransactionsInner(); transactionsInner.setTransactionId(element.getKey().toString()); transactionsInner.setState(mapConfidenceToState(element.getValue().getConfidence())); txes.add(transactionsInner); } return txes; }
@Override public void onLoadFinished(final Loader<List<StoredBlock>> loader, final List<StoredBlock> blocks) { adapter.replace(blocks); viewGroup.setDisplayedChild(1); final Loader<Set<Transaction>> transactionLoader = loaderManager.getLoader(ID_TRANSACTION_LOADER); if (transactionLoader != null && transactionLoader.isStarted()) transactionLoader.forceLoad(); }
public static SendRequest emptyWallet(Address destination) { SendRequest req = new SendRequest(); final NetworkParameters parameters = destination.getParameters(); checkNotNull(parameters, "Address is for an unknown network"); req.tx = new Transaction(parameters); req.tx.addOutput(Coin.ZERO, destination); req.emptyWallet = true; return req; }
/** * */ @Override public List<CoinTransaction> getTransactionList() { List<CoinTransaction> transactions = new ArrayList<>(); Set<Transaction> txs = _coin.getWalletManager().wallet().getTransactions(true); for (Transaction tx : txs) { Coin amount = tx.getValue(_coin.getWalletManager().wallet()); String hash = tx.getHash().toString(); String amountStr = amount.toPlainString(); String fee = ""; String confirmationStr = "CONFIRMED"; if (tx.getFee() != null) { fee = tx.getFee().toPlainString(); } TransactionConfidence confidence = tx.getConfidence(); if (confidence.getDepthInBlocks() < 6) { confirmationStr = confidence.getDepthInBlocks() + " CONFIRMATIONS"; } TransactionConfidence.ConfidenceType cType = confidence.getConfidenceType(); CoinTransaction coinTransaction = new CoinTransaction(fee, hash, amountStr, confirmationStr, tx.getUpdateTime()); transactions.add(coinTransaction); } return transactions; }
/** * A wallet app should call this from time to time in order to let the wallet craft and send transactions needed * to re-organise coins internally. A good time to call this would be after receiving coins for an unencrypted * wallet, or after sending money for an encrypted wallet. If you have an encrypted wallet and just want to know * if some maintenance needs doing, call this method with andSend set to false and look at the returned list of * transactions. Maintenance might also include internal changes that involve some processing or work but * which don't require making transactions - these will happen automatically unless the password is required * in which case an exception will be thrown. * * @param aesKey the users password, if any. * @param signAndSend if true, send the transactions via the tx broadcaster and return them, if false just return them. * @return A list of transactions that the wallet just made/will make for internal maintenance. Might be empty. * @throws org.bitcoinj.wallet.DeterministicUpgradeRequiresPassword if key rotation requires the users password. */ public ListenableFuture<List<Transaction>> doMaintenance(@Nullable KeyParameter aesKey, boolean signAndSend) throws DeterministicUpgradeRequiresPassword { List<Transaction> txns; lock.lock(); keyChainGroupLock.lock(); try { txns = maybeRotateKeys(aesKey, signAndSend); if (!signAndSend) return Futures.immediateFuture(txns); } finally { keyChainGroupLock.unlock(); lock.unlock(); } checkState(!lock.isHeldByCurrentThread()); ArrayList<ListenableFuture<Transaction>> futures = new ArrayList<>(txns.size()); TransactionBroadcaster broadcaster = vTransactionBroadcaster; for (Transaction tx : txns) { try { final ListenableFuture<Transaction> future = broadcaster.broadcastTransaction(tx).future(); futures.add(future); Futures.addCallback(future, new FutureCallback<Transaction>() { @Override public void onSuccess(Transaction transaction) { log.info("Successfully broadcast key rotation tx: {}", transaction); } @Override public void onFailure(Throwable throwable) { log.error("Failed to broadcast key rotation tx", throwable); } }); } catch (Exception e) { log.error("Failed to broadcast rekey tx", e); } } return Futures.allAsList(futures); }
public void sendBroadcastAnnouncement(BroadcastAnnouncement ba, File f, ProofMessage pm, int lockTime) throws InsufficientMoneyException { //build transaction Transaction tx = new Transaction(params); Script s = ba.buildScript(); System.out.println("Script size is " + s.SIG_SIZE); //System.out.println(s.getScriptType()); ECKey psnymKey = new ECKey(); long unixTime = System.currentTimeMillis() / 1000L; //TODO use bitcoin nets median time tx.setLockTime(CLTVScriptPair.currentBitcoinBIP113Time(bc)-1); CLTVScriptPair sp = new CLTVScriptPair(psnymKey, CLTVScriptPair.currentBitcoinBIP113Time(bc)+lockTime); w.importKey(psnymKey); tx.addOutput(new TransactionOutput(params, tx, pm.getLastTransactionOutput().getValue().subtract(estimateBroadcastFee()), sp.getPubKeyScript().getProgram())); tx.addOutput(Coin.ZERO, s); tx.addInput(pm.getLastTransactionOutput()); tx.getInput(0).setSequenceNumber(3); //the concrete value doesn't matter, this is just for cltv tx.getInput(0).setScriptSig(pm.getScriptPair().calculateSigScript(tx, 0, w)); try { w.commitTx(tx); w.saveToFile(f); } catch (IOException e1) { e1.printStackTrace(); } TransactionBroadcast broadcast = pg.broadcastTransaction(tx); pm.addTransaction(tx, 0, sp); pm.writeToFile(); System.out.println("save broadcast announcement to file"); }
public boolean isValidPath() { //check that the transaction build a path and are not just random txs, //by checking the tx hashes with those of the outpoints for(int i=validationPath.size()-1; i > 1; i--) { Transaction tx = validationPath.get(i); if(!tx.getInput(outputIndices.get(i)).getOutpoint().getHash().equals(validationPath.get(i-1).getHash())) { System.out.println("not a valid path!"); return false; } } return true; }
@Override public void onActivityResult(final int requestCode, final int resultCode, final Intent intent) { if (requestCode == REQUEST_CODE_SCAN && resultCode == Activity.RESULT_OK) { final String input = intent.getStringExtra(ScanActivity.INTENT_EXTRA_RESULT); new StringInputParser(input) { @Override protected void handlePaymentIntent(final PaymentIntent paymentIntent) { SendCoinsActivity.start(WalletActivity.this, paymentIntent); } @Override protected void handlePrivateKey(final VersionedChecksummedBytes key) { if (Constants.ENABLE_SWEEP_WALLET) SweepWalletActivity.start(WalletActivity.this, key); else super.handlePrivateKey(key); } @Override protected void handleDirectTransaction(final Transaction tx) throws VerificationException { application.processDirectTransaction(tx); } @Override protected void error(final int messageResId, final Object... messageArgs) { dialog(WalletActivity.this, null, R.string.button_scan, messageResId, messageArgs); } }.parse(); } }
private void writeObject(ObjectOutputStream oos) throws IOException { //List<byte[]> txs = new ArrayList<byte[]>(); //List<Integer> intList = new ArrayList<Integer>(); System.out.println("serialize proof message, appearedinchainheight is " + this.appearedInChainheight); oos.writeInt(appearedInChainheight); oos.writeObject(sp); for(Integer i : this.outputIndices) { oos.writeObject(i); } for(Transaction tx : this.validationPath) { oos.writeObject(tx.bitcoinSerialize()); } }
@Override public String toString() { String retValue = null; StringBuilder sb = new StringBuilder(); sb.append(this.sp.toString()); sb.append("----------\n"); for(Transaction tx : this.validationPath) { sb.append(tx.toString()); sb.append("----------\n"); } retValue = sb.toString(); return retValue; }
protected void queueOnCoinsReceived(final Transaction tx, final Coin balance, final Coin newBalance) { checkState(lock.isHeldByCurrentThread()); for (final ListenerRegistration<WalletCoinsReceivedEventListener> registration : coinsReceivedListeners) { registration.executor.execute(new Runnable() { @Override public void run() { registration.listener.onCoinsReceived(Wallet.this, tx, balance, newBalance); } }); } }
@Override public void onActivityResult(final int requestCode, final int resultCode, final Intent intent) { if (requestCode == REQUEST_CODE_SCAN && resultCode == Activity.RESULT_OK) { final String input = intent.getStringExtra(ScanActivity.INTENT_EXTRA_RESULT); new StringInputParser(input) { @Override protected void handlePaymentIntent(final PaymentIntent paymentIntent) { // workaround for "IllegalStateException: Can not perform this action after // onSaveInstanceState" handler.postDelayed(new Runnable() { @Override public void run() { if (paymentIntent.hasAddress()) { final Address address = paymentIntent.getAddress(); if (!wallet.isPubKeyHashMine(address.getHash160())) EditAddressBookEntryFragment.edit(getFragmentManager(), address); else dialog(activity, null, R.string.address_book_options_scan_title, R.string.address_book_options_scan_own_address); } else { dialog(activity, null, R.string.address_book_options_scan_title, R.string.address_book_options_scan_invalid); } } }, 500); } @Override protected void handleDirectTransaction(final Transaction transaction) throws VerificationException { cannotClassify(input); } @Override protected void error(final int messageResId, final Object... messageArgs) { dialog(activity, null, R.string.address_book_options_scan_title, messageResId, messageArgs); } }.parse(); } }
private boolean checkTx(Transaction mixTx, Transaction rcvdTxToCheck) { if(rcvdTxToCheck.getInputs().size() > 2 || rcvdTxToCheck.getOutputs().size() > 2) { System.out.println("checktx failed, num of txinputs is " + rcvdTxToCheck.getInputs().size() + " num of outputs is " + rcvdTxToCheck.getOutputs().size()); return false; } if(rcvdTxToCheck.getOutputs().size() == 2) { if(!rcvdTxToCheck.getOutput(0).getValue().equals(rcvdTxToCheck.getOutput(1).getValue())) { System.out.println("value of outputs is different, checktx fails "); return false; } } for(int i=0; i < mixTx.getInputs().size(); i++) { if(!mixTx.getInput(i).getOutpoint().equals(rcvdTxToCheck.getInput(i).getOutpoint())) { System.out.println("the outpoints do not match, checktx fails"); return false; } } for(int i=0; i < mixTx.getOutputs().size(); i++) { if(!mixTx.getOutput(i).equals(rcvdTxToCheck.getOutput(i))) { System.out.println("outputs are sth else, checktx fails"); System.out.println("mixTx ----------"); System.out.println(mixTx.toString()); System.out.println("rcvdtxtocheck--------"); System.out.println(rcvdTxToCheck.toString()); return false; } } return true; }
/** Sub-classes can override this to just customize whether transactions are usable, but keep age sorting. */ protected boolean shouldSelect(Transaction tx) { if (tx != null) { return isSelectable(tx); } return true; }
public MixPartnerDiscovery(NetworkParameters params, PeerGroup pg, BlockChain bc, Wallet wallet) { this.pg = pg; this.bc = bc; this.head = null; this.wallet = wallet; this.broadcasts = new ArrayList<Transaction>(); this.listeners = new ArrayList<BroadcastAnnouncementChangeEventListener>(); }
public void searchBlockForPartner(Block block) throws NullPointerException { if(this.head == null) { throw new NullPointerException("Block must not be null"); } List<Transaction> listTxs = block.getTransactions(); for(Transaction tx : listTxs) { System.out.println("test transaction " + tx.getHashAsString()); if(isTransactionBroadcastAnnouncement(tx)) { broadcasts.add(tx); System.out.println("found a broadcast announcement!"); System.out.println(tx); } } }
public boolean isTransactionBroadcastAnnouncement(Transaction tx) { List<TransactionOutput> outputs = tx.getOutputs(); TransactionOutput scndOutput = outputs.get(1); if(!scndOutput.getScriptPubKey().isOpReturn()) { return false; } byte[] script = scndOutput.getScriptBytes(); //check magic numbers that are defined in BroadcastAnnouncement return BroadcastAnnouncement.isBroadcastAnnouncementScript(script); }