void undo(BlockImpl block) throws TransactionType.UndoNotSupportedException { block.undo(); List<Transaction> addedUnconfirmedTransactions = new ArrayList<>(); for (TransactionImpl transaction : block.getTransactions()) { TransactionHashInfo transactionHashInfo = transactionHashes.get(transaction.getHash()); if (transactionHashInfo != null && transactionHashInfo.transactionId.equals(transaction.getId())) { transactionHashes.remove(transaction.getHash()); } unconfirmedTransactions.put(transaction.getId(), transaction); unconfirmedTransactionHashes.put(transaction.getHash(), transaction); transaction.undo(); addedUnconfirmedTransactions.add(transaction); } if (addedUnconfirmedTransactions.size() > 0) { transactionListeners.notify( addedUnconfirmedTransactions, TransactionProcessor.Event.ADDED_UNCONFIRMED_TRANSACTIONS); } }
void removeUnconfirmedTransactions(Collection<TransactionImpl> transactions) { List<Transaction> removedList = new ArrayList<>(); for (TransactionImpl transaction : transactions) { if (unconfirmedTransactions.remove(transaction.getId()) != null) { transaction.undoUnconfirmed(); unconfirmedTransactionHashes.remove(transaction.getHash()); removedList.add(transaction); } } transactionListeners.notify(removedList, Event.REMOVED_UNCONFIRMED_TRANSACTIONS); }
void apply(BlockImpl block) { block.apply(); for (TransactionImpl transaction : block.getTransactions()) { if (!unconfirmedTransactions.containsKey(transaction.getId())) { transaction.applyUnconfirmed(); } // TODO: Phaser not yet implemented // Phaser.processTransaction(transaction); transaction.apply(); transactionHashes.put(transaction.getHash(), new TransactionHashInfo(transaction)); } purgeExpiredHashes(block.getTimestamp()); }
TransactionImpl checkTransactionHashes(BlockImpl block) { TransactionImpl duplicateTransaction = null; for (TransactionImpl transaction : block.getTransactions()) { if (transactionHashes.putIfAbsent(transaction.getHash(), new TransactionHashInfo(transaction)) != null && block.getHeight() != 58294) { duplicateTransaction = transaction; break; } } if (duplicateTransaction != null) { for (TransactionImpl transaction : block.getTransactions()) { if (!transaction.equals(duplicateTransaction)) { TransactionHashInfo transactionHashInfo = transactionHashes.get(transaction.getHash()); if (transactionHashInfo != null && transactionHashInfo.transactionId.equals(transaction.getId())) { transactionHashes.remove(transaction.getHash()); } } } } return duplicateTransaction; }
@Override public void run() { try { try { int curTime = Convert.getEpochTime(); List<Transaction> removedUnconfirmedTransactions = new ArrayList<>(); synchronized (BlockchainImpl.getInstance()) { Iterator<TransactionImpl> iterator = unconfirmedTransactions.values().iterator(); while (iterator.hasNext()) { TransactionImpl transaction = iterator.next(); if (transaction.getExpiration() < curTime) { iterator.remove(); unconfirmedTransactionHashes.remove(transaction.getHash()); transaction.undoUnconfirmed(); removedUnconfirmedTransactions.add(transaction); } } } if (removedUnconfirmedTransactions.size() > 0) { transactionListeners.notify( removedUnconfirmedTransactions, Event.REMOVED_UNCONFIRMED_TRANSACTIONS); } } catch (Exception e) { Logger.logDebugMessage("Error removing unconfirmed transactions", e); } } catch (Throwable t) { Logger.logMessage("CRITICAL ERROR. PLEASE REPORT TO THE DEVELOPERS.\n" + t.toString()); t.printStackTrace(); System.exit(1); } }
private List<Transaction> processTransactions( List<TransactionImpl> transactions, final boolean sendToPeers) { List<Transaction> sendToPeersTransactions = new ArrayList<>(); List<Transaction> addedUnconfirmedTransactions = new ArrayList<>(); List<Transaction> addedDoubleSpendingTransactions = new ArrayList<>(); for (TransactionImpl transaction : transactions) { try { int curTime = Convert.getEpochTime(); if (transaction.getTimestamp() > curTime + 15 || transaction.getExpiration() < curTime || transaction.getDeadline() > 1440) { continue; } synchronized (BlockchainImpl.getInstance()) { Long id = transaction.getId(); if (TransactionDb.hasTransaction(id) || unconfirmedTransactions.containsKey(id) || !transaction.verify()) { continue; } if (transactionHashes.containsKey(transaction.getHash()) || unconfirmedTransactionHashes.containsKey(transaction.getHash())) { continue; } if (transaction.applyUnconfirmed()) { if (sendToPeers) { if (nonBroadcastedTransactions.containsKey(id)) { Logger.logDebugMessage( "Received back transaction " + transaction.getStringId() + " that we generated, will not forward to peers"); nonBroadcastedTransactions.remove(id); } else { sendToPeersTransactions.add(transaction); } } unconfirmedTransactions.put(id, transaction); unconfirmedTransactionHashes.put(transaction.getHash(), transaction); addedUnconfirmedTransactions.add(transaction); } else { addedDoubleSpendingTransactions.add(transaction); } } } catch (RuntimeException e) { Logger.logMessage("Error processing transaction", e); } } if (sendToPeersTransactions.size() > 0) { Peers.sendToSomePeers(sendToPeersTransactions); } if (addedUnconfirmedTransactions.size() > 0) { transactionListeners.notify( addedUnconfirmedTransactions, Event.ADDED_UNCONFIRMED_TRANSACTIONS); } if (addedDoubleSpendingTransactions.size() > 0) { transactionListeners.notify( addedDoubleSpendingTransactions, Event.ADDED_DOUBLESPENDING_TRANSACTIONS); } return addedUnconfirmedTransactions; }