private static void sendTransactionsToListener( StoredBlock block, NewBlockType blockType, BlockChainListener listener, int relativityOffset, List<Transaction> transactions, boolean clone, Set<Sha256Hash> falsePositives) throws VerificationException { for (Transaction tx : transactions) { try { if (listener.isTransactionRelevant(tx)) { falsePositives.remove(tx.getHash()); if (clone) tx = new Transaction(tx.params, tx.bitcoinSerialize()); listener.receiveFromBlock(tx, block, blockType, relativityOffset++); } } catch (ScriptException e) { // We don't want scripts we don't understand to break the block chain so just note that this // tx was // not scanned here and continue. log.warn("Failed to parse a script: " + e.toString()); } catch (ProtocolException e) { // Failed to duplicate tx, should never happen. throw new RuntimeException(e); } } }
private static void informListenerForNewTransactions( Block block, NewBlockType newBlockType, @Nullable List<Sha256Hash> filteredTxHashList, @Nullable Map<Sha256Hash, Transaction> filteredTxn, StoredBlock newStoredBlock, boolean first, BlockChainListener listener, Set<Sha256Hash> falsePositives) throws VerificationException { if (block.transactions != null) { // If this is not the first wallet, ask for the transactions to be duplicated before being // given // to the wallet when relevant. This ensures that if we have two connected wallets and a tx // that // is relevant to both of them, they don't end up accidentally sharing the same object (which // can // result in temporary in-memory corruption during re-orgs). See bug 257. We only duplicate in // the case of multiple wallets to avoid an unnecessary efficiency hit in the common case. sendTransactionsToListener( newStoredBlock, newBlockType, listener, 0, block.transactions, !first, falsePositives); } else if (filteredTxHashList != null) { checkNotNull(filteredTxn); // We must send transactions to listeners in the order they appeared in the block - thus we // iterate over the // set of hashes and call sendTransactionsToListener with individual txn when they have not // already been // seen in loose broadcasts - otherwise notifyTransactionIsInBlock on the hash. int relativityOffset = 0; for (Sha256Hash hash : filteredTxHashList) { Transaction tx = filteredTxn.get(hash); if (tx != null) { sendTransactionsToListener( newStoredBlock, newBlockType, listener, relativityOffset, Collections.singletonList(tx), !first, falsePositives); } else { if (listener.notifyTransactionIsInBlock( hash, newStoredBlock, newBlockType, relativityOffset)) { falsePositives.remove(hash); } } relativityOffset++; } } }