From d5bdcb672bc51d6399e40131947bdc0d17c76ee1 Mon Sep 17 00:00:00 2001 From: Brabantian Date: Thu, 6 Dec 2018 21:20:39 +0100 Subject: [PATCH 1/3] Better logging + small improvements UTStore --- src/brs/peer/Peers.java | 2 +- .../ReservedBalanceCache.java | 4 +- .../UnconfirmedTransactionStore.java | 7 +- .../UnconfirmedTransactionStoreImpl.java | 182 +++++++++--------- .../UnconfirmedTransactionStoreTest.java | 14 +- 5 files changed, 103 insertions(+), 106 deletions(-) diff --git a/src/brs/peer/Peers.java b/src/brs/peer/Peers.java index de703a13d..4b5b8cc9b 100644 --- a/src/brs/peer/Peers.java +++ b/src/brs/peer/Peers.java @@ -815,7 +815,7 @@ public synchronized static void feedingTime(Peer peer, Function> foodDispenser, BiConsumer> doneFeedingLog) { List transactionsToSend = foodDispenser.apply(peer); if(! transactionsToSend.isEmpty()) { - logger.debug("Feeding {} {} transactions", peer.getPeerAddress(), transactionsToSend.size()); + logger.info("Feeding {} {} transactions", peer.getPeerAddress(), transactionsToSend.size()); peer.send(sendUnconfirmedTransactionsRequest(transactionsToSend)); } else { logger.debug("No need to feed {}", peer.getPeerAddress()); diff --git a/src/brs/unconfirmedtransactions/ReservedBalanceCache.java b/src/brs/unconfirmedtransactions/ReservedBalanceCache.java index 67532182d..5ddd326d8 100644 --- a/src/brs/unconfirmedtransactions/ReservedBalanceCache.java +++ b/src/brs/unconfirmedtransactions/ReservedBalanceCache.java @@ -39,11 +39,11 @@ void reserveBalanceAndPut(Transaction transaction) throws BurstException.Validat ); if (senderAccount == null) { - LOGGER.debug(String.format("Transaction %d: Account %d does not exist and has no balance. Required funds: %d", transaction.getId(), transaction.getSenderId(), amountNQT)); + LOGGER.info(String.format("Transaction %d: Account %d does not exist and has no balance. Required funds: %d", transaction.getId(), transaction.getSenderId(), amountNQT)); throw new BurstException.NotCurrentlyValidException("Account unknown"); } else if ( amountNQT > senderAccount.getUnconfirmedBalanceNQT() ) { - LOGGER.debug(String.format("Transaction %d: Account %d balance too low. You have %d > %d Balance", + LOGGER.info(String.format("Transaction %d: Account %d balance too low. You have %d > %d Balance", transaction.getId(), transaction.getSenderId(), amountNQT, senderAccount.getUnconfirmedBalanceNQT() )); diff --git a/src/brs/unconfirmedtransactions/UnconfirmedTransactionStore.java b/src/brs/unconfirmedtransactions/UnconfirmedTransactionStore.java index d2f4f458d..40abe3d33 100644 --- a/src/brs/unconfirmedtransactions/UnconfirmedTransactionStore.java +++ b/src/brs/unconfirmedtransactions/UnconfirmedTransactionStore.java @@ -18,20 +18,15 @@ public interface UnconfirmedTransactionStore { List getAllFor(Peer peer); - ///TimedUnconfirmedTransactionOverview getAllSince(long timestampInMillis, long maxAmount); - - void forEach(Consumer consumer); - void remove(Transaction transaction); void clear(); - /** * Review which transactions are still eligible to stay * @return The list of removed transactions */ - List resetAccountBalances(); + void resetAccountBalances(); void markFingerPrintsOf(Peer peer, List transactions); diff --git a/src/brs/unconfirmedtransactions/UnconfirmedTransactionStoreImpl.java b/src/brs/unconfirmedtransactions/UnconfirmedTransactionStoreImpl.java index 81ef9a96b..d26209d5f 100644 --- a/src/brs/unconfirmedtransactions/UnconfirmedTransactionStoreImpl.java +++ b/src/brs/unconfirmedtransactions/UnconfirmedTransactionStoreImpl.java @@ -14,14 +14,13 @@ import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; +import java.util.Optional; import java.util.SortedMap; import java.util.TreeMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; import java.util.stream.Collectors; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; @@ -77,70 +76,48 @@ public UnconfirmedTransactionStoreImpl(TimeService timeService, PropertyService @Override public boolean put(Transaction transaction, Peer peer) throws ValidationException { synchronized (internalStore) { - if(transactionIsCurrentlyInCache(transaction)) { - if(peer != null) { - logger.debug("Transaction {}: Added fingerprint of {}", transaction.getId(), peer.getPeerAddress()); + if (transactionIsCurrentlyInCache(transaction)) { + if (peer != null) { + logger.info("Transaction {}: Added fingerprint of {}", transaction.getId(), peer.getPeerAddress()); fingerPrintsOverview.get(transaction).add(peer); } - } else { - if (transactionCanBeAddedToCache(transaction)) { - final TransactionDuplicationResult duplicationInformation = transactionDuplicatesChecker.removeCheaperDuplicate(transaction); + } else if (transactionCanBeAddedToCache(transaction)) { + this.reservedBalanceCache.reserveBalanceAndPut(transaction); - if (duplicationInformation.isDuplicate()) { - final Transaction duplicatedTransaction = duplicationInformation.getTransaction(); + final TransactionDuplicationResult duplicationInformation = transactionDuplicatesChecker.removeCheaperDuplicate(transaction); - if (duplicatedTransaction != null && duplicatedTransaction != transaction) { - logger.debug("Transaction {}: Adding more expensive duplicate transaction", transaction.getId()); - removeTransaction(duplicationInformation.getTransaction()); + if (duplicationInformation.isDuplicate()) { + final Transaction duplicatedTransaction = duplicationInformation.getTransaction(); - addTransaction(transaction, peer); + if (duplicatedTransaction != null && duplicatedTransaction != transaction) { + logger.info("Transaction {}: Adding more expensive duplicate transaction", transaction.getId()); + removeTransaction(duplicationInformation.getTransaction()); + this.reservedBalanceCache.refundBalance(duplicationInformation.getTransaction()); - if (totalSize > maxSize) { - removeCheapestFirstToExpireTransaction(); - } - } else { - logger.debug("Transaction {}: Will not add a cheaper duplicate UT", transaction.getId()); - } - } else { addTransaction(transaction, peer); - logger.debug( - "Cache size: " + totalSize + "/" + maxSize + " Added UT " + transaction.getId() + " " + transaction.getSenderId() + " " + transaction.getAmountNQT() + " " + transaction.getFeeNQT()); + if (totalSize > maxSize) { removeCheapestFirstToExpireTransaction(); } + } else { + logger.info("Transaction {}: Will not add a cheaper duplicate UT", transaction.getId()); } - - return true; } else { - logger.info("Transaction {}: Will not add UT due to duplication, or too full", transaction.getId()); + addTransaction(transaction, peer); + logger.info("Cache size: {}/{} added {} from sender {}", totalSize, maxSize, transaction.getId(), transaction.getSenderId()); } + + if (totalSize > maxSize) { + removeCheapestFirstToExpireTransaction(); + } + + return true; } return false; } } - private boolean transactionCanBeAddedToCache(Transaction transaction) { - return transactionIsCurrentlyValid(transaction) - && ! cacheFullAndTransactionCheaperThanAllTheRest(transaction) - && ! tooManyTransactionsWithReferencedFullHash(transaction) - && ! tooManyTransactionsForSlotSize(transaction); - } - - private boolean tooManyTransactionsForSlotSize(Transaction transaction) { - final long slotHeight = this.amountSlotForTransaction(transaction); - - return this.internalStore.containsKey(slotHeight) && this.internalStore.get(slotHeight).size() == slotHeight * 360; - } - - private boolean tooManyTransactionsWithReferencedFullHash(Transaction transaction) { - return ! StringUtils.isEmpty(transaction.getReferencedTransactionFullHash()) && maxPercentageUnconfirmedTransactionsFullHash <= (((numberUnconfirmedTransactionsFullHash + 1) * 100) / maxSize); - } - - private boolean cacheFullAndTransactionCheaperThanAllTheRest(Transaction transaction) { - return totalSize == maxSize && internalStore.firstKey() > amountSlotForTransaction(transaction); - } - @Override public Transaction get(Long transactionId) { synchronized (internalStore) { @@ -180,7 +157,7 @@ public List getAll() { public List getAllFor(Peer peer) { synchronized (internalStore) { final List untouchedTransactions = fingerPrintsOverview.entrySet().stream() - .filter(e -> ! e.getValue().contains(peer)) + .filter(e -> !e.getValue().contains(peer)) .map(e -> e.getKey()).collect(Collectors.toList()); final ArrayList resultList = new ArrayList<>(); @@ -201,15 +178,6 @@ public List getAllFor(Peer peer) { } } - @Override - public void forEach(Consumer consumer) { - synchronized (internalStore) { - for (List amountSlot : internalStore.values()) { - amountSlot.stream().forEach(consumer); - } - } - } - @Override public void remove(Transaction transaction) { synchronized (internalStore) { @@ -223,7 +191,7 @@ public void remove(Transaction transaction) { @Override public void clear() { synchronized (internalStore) { - logger.debug("Clearing UTStore"); + logger.info("Clearing UTStore"); totalSize = 0; internalStore.clear(); reservedBalanceCache.clear(); @@ -232,9 +200,11 @@ public void clear() { } @Override - public List resetAccountBalances() { + public void resetAccountBalances() { synchronized (internalStore) { - return reservedBalanceCache.rebuild(getAll()); + for(Transaction insufficientFundsTransactions: reservedBalanceCache.rebuild(getAll())) { + this.removeTransaction(insufficientFundsTransactions); + } } } @@ -242,7 +212,7 @@ public List resetAccountBalances() { public void markFingerPrintsOf(Peer peer, List transactions) { synchronized (internalStore) { for (Transaction transaction : transactions) { - if(fingerPrintsOverview.containsKey(transaction)) { + if (fingerPrintsOverview.containsKey(transaction)) { fingerPrintsOverview.get(transaction).add(peer); } } @@ -252,8 +222,8 @@ public void markFingerPrintsOf(Peer peer, List transactions) { @Override public void removeForgedTransactions(List transactions) { synchronized (internalStore) { - for(Transaction t:transactions) { - if(exists(t.getId())) { + for (Transaction t : transactions) { + if (exists(t.getId())) { removeTransaction(t); } } @@ -265,22 +235,65 @@ private boolean transactionIsCurrentlyInCache(Transaction transaction) { return amountSlot != null && amountSlot.stream().anyMatch(t -> t.getId() == transaction.getId()); } - private void addTransaction(Transaction transaction, Peer peer) throws ValidationException { - this.reservedBalanceCache.reserveBalanceAndPut(transaction); + private boolean transactionCanBeAddedToCache(Transaction transaction) { + return transactionIsCurrentlyNotExpired(transaction) + && !cacheFullAndTransactionCheaperThanAllTheRest(transaction) + && !tooManyTransactionsWithReferencedFullHash(transaction) + && !tooManyTransactionsForSlotSize(transaction); + } + + private boolean tooManyTransactionsForSlotSize(Transaction transaction) { + final long slotHeight = this.amountSlotForTransaction(transaction); + + if (this.internalStore.containsKey(slotHeight) && this.internalStore.get(slotHeight).size() == slotHeight * 360) { + logger.info("Transaction {}: Not added because slot {} is full", transaction.getId(), slotHeight); + return true; + } + + return false; + } + + private boolean tooManyTransactionsWithReferencedFullHash(Transaction transaction) { + if (!StringUtils.isEmpty(transaction.getReferencedTransactionFullHash()) && maxPercentageUnconfirmedTransactionsFullHash <= (((numberUnconfirmedTransactionsFullHash + 1) * 100) / maxSize)) { + logger.info("Transaction {}: Not added because too many transactions with referenced full hash", transaction.getId()); + return true; + } + + return false; + } + + private boolean cacheFullAndTransactionCheaperThanAllTheRest(Transaction transaction) { + if (totalSize == maxSize && internalStore.firstKey() > amountSlotForTransaction(transaction)) { + logger.info("Transaction {}: Not added because cache is full and transaction is cheaper than all the rest", transaction.getId()); + return true; + } + return false; + } + + private boolean transactionIsCurrentlyNotExpired(Transaction transaction) { + if (timeService.getEpochTime() < transaction.getExpiration()) { + return true; + } else { + logger.info("Transaction {} past expiration: {}", transaction.getId(), transaction.getExpiration()); + return false; + } + } + + private void addTransaction(Transaction transaction, Peer peer) throws ValidationException { final List slot = getOrCreateAmountSlotForTransaction(transaction); slot.add(transaction); totalSize++; fingerPrintsOverview.put(transaction, new HashSet<>()); - if(peer != null) { + if (peer != null) { fingerPrintsOverview.get(transaction).add(peer); } logger.debug("Adding Transaction {} from Peer {}", transaction.getId(), (peer == null ? "Ourself" : peer.getPeerAddress())); - if(! StringUtils.isEmpty(transaction.getReferencedTransactionFullHash())) { + if (!StringUtils.isEmpty(transaction.getReferencedTransactionFullHash())) { numberUnconfirmedTransactionsFullHash++; } } @@ -301,18 +314,13 @@ private long amountSlotForTransaction(Transaction transaction) { } private void removeCheapestFirstToExpireTransaction() { - this.internalStore.get(this.internalStore.firstKey()).stream() - //.map(UnconfirmedTransactionTiming::getTransaction) + final Optional cheapestFirstToExpireTransaction = this.internalStore.get(this.internalStore.firstKey()).stream() .sorted(Comparator.comparingLong(Transaction::getFeeNQT).thenComparing(Transaction::getExpiration).thenComparing(Transaction::getId)) - .findFirst().ifPresent(t -> removeTransaction(t)); - } + .findFirst(); - private boolean transactionIsCurrentlyValid(Transaction transaction) { - if(timeService.getEpochTime() < transaction.getExpiration()) { - return true; - } else { - logger.debug("Transaction {} past expiration: {}", transaction.getId(), transaction.getExpiration()); - return false; + if (cheapestFirstToExpireTransaction.isPresent()) { + reservedBalanceCache.refundBalance(cheapestFirstToExpireTransaction.get()); + removeTransaction(cheapestFirstToExpireTransaction.get()); } } @@ -321,23 +329,13 @@ private void removeTransaction(Transaction transaction) { final List amountSlot = internalStore.get(amountSlotNumber); - final Iterator transactionSlotIterator = amountSlot.iterator(); - fingerPrintsOverview.remove(transaction); + amountSlot.remove(transaction); + totalSize--; + transactionDuplicatesChecker.removeTransaction(transaction); - while (transactionSlotIterator.hasNext()) { - final Transaction utt = transactionSlotIterator.next(); - if (utt.getId() == transaction.getId()) { - transactionSlotIterator.remove(); - transactionDuplicatesChecker.removeTransaction(transaction); - this.reservedBalanceCache.refundBalance(transaction); - totalSize--; - - if(! StringUtils.isEmpty(transaction.getReferencedTransactionFullHash())) { - numberUnconfirmedTransactionsFullHash--; - } - break; - } + if (!StringUtils.isEmpty(transaction.getReferencedTransactionFullHash())) { + numberUnconfirmedTransactionsFullHash--; } if (amountSlot.isEmpty()) { diff --git a/test/java/brs/unconfirmedtransactions/UnconfirmedTransactionStoreTest.java b/test/java/brs/unconfirmedtransactions/UnconfirmedTransactionStoreTest.java index c0a502858..5889636af 100644 --- a/test/java/brs/unconfirmedtransactions/UnconfirmedTransactionStoreTest.java +++ b/test/java/brs/unconfirmedtransactions/UnconfirmedTransactionStoreTest.java @@ -238,18 +238,22 @@ public void unconfirmedTransactionGetsDeniedForNotEnoughUnconfirmedBalance() thr public void addingNewUnconfirmedTransactionWithSameIDResultsInNothingChanging() throws ValidationException { when(mockBlockChain.getHeight()).thenReturn(20); + Peer mockPeer = mock(Peer.class); + + when(mockPeer.getPeerAddress()).thenReturn("mockPeer"); + Builder transactionBuilder = new Builder((byte) 1, TestConstants.TEST_PUBLIC_KEY_BYTES, 1, Constants.MAX_BALANCE_NQT - 100000, timeService.getEpochTime() + 50000, (short) 500, ORDINARY_PAYMENT) .id(1).senderId(123L); Transaction transaction1 = transactionBuilder.build(); transaction1.sign(TestConstants.TEST_SECRET_PHRASE); - t.put(transaction1, null); + t.put(transaction1, mockPeer); Transaction transaction2 = transactionBuilder.build(); transaction2.sign(TestConstants.TEST_SECRET_PHRASE); - t.put(transaction2, null); + t.put(transaction2, mockPeer); assertEquals(1, t.getAll().size()); } @@ -260,7 +264,7 @@ public void whenMaximumNumberOfTransactionsWithFullHashReferenceIsReachedFollowi when(mockBlockChain.getHeight()).thenReturn(20); - for (int i = 1; i <= 500; i++) { + for (int i = 1; i <= 414; i++) { Transaction transaction = new Transaction.Builder((byte) 1, TestConstants.TEST_PUBLIC_KEY_BYTES, i, FEE_QUANT * 2, timeService.getEpochTime() + 50000, (short) 500, ORDINARY_PAYMENT) .id(i).senderId(123L).referencedTransactionFullHash("b33f").build(); transaction.sign(TestConstants.TEST_SECRET_PHRASE); @@ -276,7 +280,7 @@ public void whenMaximumNumberOfTransactionsForSlotSizeIsReachedFollowingOnesAreI when(mockBlockChain.getHeight()).thenReturn(20); - for (int i = 1; i <= 500; i++) { + for (int i = 1; i <= 365; i++) { Transaction transaction = new Transaction.Builder((byte) 1, TestConstants.TEST_PUBLIC_KEY_BYTES, i, FEE_QUANT, timeService.getEpochTime() + 50000, (short) 500, ORDINARY_PAYMENT) .id(i).senderId(123L).build(); transaction.sign(TestConstants.TEST_SECRET_PHRASE); @@ -285,7 +289,7 @@ public void whenMaximumNumberOfTransactionsForSlotSizeIsReachedFollowingOnesAreI assertEquals(360, t.getAll().size()); - for (int i = 1; i <= 800; i++) { + for (int i = 1; i <= 725; i++) { Transaction transaction = new Transaction.Builder((byte) 1, TestConstants.TEST_PUBLIC_KEY_BYTES, i, FEE_QUANT * 2, timeService.getEpochTime() + 50000, (short) 500, ORDINARY_PAYMENT) .id(i).senderId(123L).build(); transaction.sign(TestConstants.TEST_SECRET_PHRASE); From 1bf0a27f81b14c5d456c97f02746bfea8d2f4d42 Mon Sep 17 00:00:00 2001 From: Brabantian Date: Thu, 6 Dec 2018 22:20:13 +0100 Subject: [PATCH 2/3] Pushing to all really is to all (max 100) && feedback to front && feeding also the original peer who we got from in UT pulling --- src/brs/TransactionProcessor.java | 2 +- src/brs/TransactionProcessorImpl.java | 39 +++++++++------------ src/brs/http/APITransactionManagerImpl.java | 4 +-- src/brs/http/BroadcastTransaction.java | 3 +- src/brs/http/common/ResultFields.java | 1 + src/brs/peer/Peers.java | 2 +- 6 files changed, 23 insertions(+), 28 deletions(-) diff --git a/src/brs/TransactionProcessor.java b/src/brs/TransactionProcessor.java index 5e1da7bb7..b1e3aede9 100644 --- a/src/brs/TransactionProcessor.java +++ b/src/brs/TransactionProcessor.java @@ -25,7 +25,7 @@ enum Event { void clearUnconfirmedTransactions(); - void broadcast(Transaction transaction) throws BurstException.ValidationException; + Integer broadcast(Transaction transaction) throws BurstException.ValidationException; void processPeerTransactions(JSONObject request, Peer peer) throws BurstException.ValidationException; diff --git a/src/brs/TransactionProcessorImpl.java b/src/brs/TransactionProcessorImpl.java index 303309cf4..86f568ad5 100644 --- a/src/brs/TransactionProcessorImpl.java +++ b/src/brs/TransactionProcessorImpl.java @@ -20,6 +20,7 @@ import java.util.concurrent.CompletableFuture; import java.util.function.BiConsumer; import java.util.function.Function; +import java.util.stream.Collectors; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.slf4j.Logger; @@ -84,11 +85,12 @@ public TransactionProcessorImpl(PropertyService propertyService, JSONArray transactionsData = (JSONArray) response.get(UNCONFIRMED_TRANSACTIONS_RESPONSE); - if (transactionsData == null || transactionsData.isEmpty()) { + if (transactionsData == null) { return; } try { List addedTransactions = processPeerTransactions(transactionsData, peer); + Peers.feedingTime(peer, foodDispenser, doneFeedingLog); if(! addedTransactions.isEmpty()) { List activePrioPlusExtra = Peers.getAllActivePriorityPlusSomeExtraPeers(); @@ -180,40 +182,25 @@ public Transaction.Builder newTransactionBuilder(byte[] senderPublicKey, long am } @Override - public void broadcast(Transaction transaction) throws BurstException.ValidationException { + public Integer broadcast(Transaction transaction) throws BurstException.ValidationException { if (! transaction.verifySignature()) { throw new BurstException.NotValidException("Transaction signature verification failed"); } List processedTransactions; if (dbs.getTransactionDb().hasTransaction(transaction.getId())) { logger.info("Transaction " + transaction.getStringId() + " already in blockchain, will not broadcast again"); - return; + return null; } if (unconfirmedTransactionStore.exists(transaction.getId())) { - /* - if (enableTransactionRebroadcasting) { - nonBroadcastedTransactions.add(transaction); - logger.info("Transaction " + transaction.getStringId() + " already in unconfirmed pool, will re-broadcast"); - } else {*/ - logger.info("Transaction " + transaction.getStringId() + " already in unconfirmed pool, will not broadcast again"); - ///} - return; + logger.info("Transaction " + transaction.getStringId() + " already in unconfirmed pool, will not broadcast again"); + return null; } processedTransactions = processTransactions(Collections.singleton(transaction), null); if(! processedTransactions.isEmpty()) { - broadcastToPeers(); - } - - if (processedTransactions.contains(transaction)) { - /* - if (enableTransactionRebroadcasting) { - nonBroadcastedTransactions.add(transaction); - } - */ - logger.debug("Accepted new transaction " + transaction.getStringId()); + return broadcastToPeers(true); } else { logger.debug("Could not accept new transaction " + transaction.getStringId()); throw new BurstException.NotValidException("Invalid transaction " + transaction.getStringId()); @@ -226,7 +213,7 @@ public void processPeerTransactions(JSONObject request, Peer peer) throws BurstE List processedTransactions = processPeerTransactions(transactionsData, peer); if(! processedTransactions.isEmpty()) { - broadcastToPeers(); + broadcastToPeers(false); } } @@ -373,10 +360,16 @@ private List processTransactions(Collection transactio } } - private void broadcastToPeers() { + private int broadcastToPeers(boolean toAll) { + List peersToSendTo = toAll ? Peers.getActivePeers().stream().limit(100).collect(Collectors.toList()) : Peers.getAllActivePriorityPlusSomeExtraPeers(); + + logger.info("Queueing up {} Peers for feeding", peersToSendTo.size()); + for(Peer p: Peers.getAllActivePriorityPlusSomeExtraPeers()) { Peers.feedingTime(p, foodDispenser, doneFeedingLog); } + + return peersToSendTo.size(); } public void revalidateUnconfirmedTransactions() { diff --git a/src/brs/http/APITransactionManagerImpl.java b/src/brs/http/APITransactionManagerImpl.java index c0806432d..40e66de28 100644 --- a/src/brs/http/APITransactionManagerImpl.java +++ b/src/brs/http/APITransactionManagerImpl.java @@ -23,6 +23,7 @@ import static brs.http.common.ResultFields.BROADCASTED_RESPONSE; import static brs.http.common.ResultFields.ERROR_RESPONSE; import static brs.http.common.ResultFields.FULL_HASH_RESPONSE; +import static brs.http.common.ResultFields.NUMBER_PEERS_SENT_TO_RESPONSE; import static brs.http.common.ResultFields.SIGNATURE_HASH_RESPONSE; import static brs.http.common.ResultFields.TRANSACTION_BYTES_RESPONSE; import static brs.http.common.ResultFields.TRANSACTION_JSON_RESPONSE; @@ -38,7 +39,6 @@ import brs.Blockchain; import brs.Burst; import brs.BurstException; -import brs.Constants; import brs.Transaction; import brs.Transaction.Builder; import brs.TransactionProcessor; @@ -187,7 +187,7 @@ public JSONStreamAware createTransaction(HttpServletRequest req, Account senderA response.put(TRANSACTION_BYTES_RESPONSE, Convert.toHexString(transaction.getBytes())); response.put(SIGNATURE_HASH_RESPONSE, Convert.toHexString(Crypto.sha256().digest(transaction.getSignature()))); if (broadcast) { - transactionProcessor.broadcast(transaction); + response.put(NUMBER_PEERS_SENT_TO_RESPONSE, transactionProcessor.broadcast(transaction)); response.put(BROADCASTED_RESPONSE, true); } else { response.put(BROADCASTED_RESPONSE, false); diff --git a/src/brs/http/BroadcastTransaction.java b/src/brs/http/BroadcastTransaction.java index 5f4256bbb..a5b3d0de9 100644 --- a/src/brs/http/BroadcastTransaction.java +++ b/src/brs/http/BroadcastTransaction.java @@ -6,6 +6,7 @@ import static brs.http.common.ResultFields.ERROR_DESCRIPTION_RESPONSE; import static brs.http.common.ResultFields.ERROR_RESPONSE; import static brs.http.common.ResultFields.FULL_HASH_RESPONSE; +import static brs.http.common.ResultFields.NUMBER_PEERS_SENT_TO_RESPONSE; import static brs.http.common.ResultFields.TRANSACTION_RESPONSE; import brs.BurstException; @@ -45,7 +46,7 @@ JSONStreamAware processRequest(HttpServletRequest req) throws BurstException { JSONObject response = new JSONObject(); try { transactionService.validate(transaction); - transactionProcessor.broadcast(transaction); + response.put(NUMBER_PEERS_SENT_TO_RESPONSE, transactionProcessor.broadcast(transaction)); response.put(TRANSACTION_RESPONSE, transaction.getStringId()); response.put(FULL_HASH_RESPONSE, transaction.getFullHash()); } catch (BurstException.ValidationException | RuntimeException e) { diff --git a/src/brs/http/common/ResultFields.java b/src/brs/http/common/ResultFields.java index ffd51153f..6d5813d38 100644 --- a/src/brs/http/common/ResultFields.java +++ b/src/brs/http/common/ResultFields.java @@ -21,6 +21,7 @@ public class ResultFields { public static final String DONE_RESPONSE = "done"; public static final String SCAN_TIME_RESPONSE = "scanTime"; public static final String BROADCASTED_RESPONSE = "broadcasted"; + public static final String NUMBER_PEERS_SENT_TO_RESPONSE = "numberPeersSentTo"; public static final String UNSIGNED_TRANSACTION_BYTES_RESPONSE = "unsignedTransactionBytes"; public static final String TRANSACTION_JSON_RESPONSE = "transactionJSON"; public static final String TRANSACTION_BYTES_RESPONSE = "transactionBytes"; diff --git a/src/brs/peer/Peers.java b/src/brs/peer/Peers.java index 4b5b8cc9b..fda07a812 100644 --- a/src/brs/peer/Peers.java +++ b/src/brs/peer/Peers.java @@ -639,7 +639,7 @@ public static Collection getAllPeers() { return allPeers; } - public static Collection getActivePeers() { + public static List getActivePeers() { List activePeers = new ArrayList<>(); for (PeerImpl peer : peers.values()) { if (peer.getState() != Peer.State.NON_CONNECTED) { From 938241d91e2da24372f9f38017d2103781fd7b73 Mon Sep 17 00:00:00 2001 From: Brabantian Date: Thu, 6 Dec 2018 22:31:14 +0100 Subject: [PATCH 3/3] ProcessBlock better logging --- src/brs/BlockchainProcessor.java | 2 +- src/brs/BlockchainProcessorImpl.java | 13 ++++--------- src/brs/peer/ProcessBlock.java | 2 +- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/brs/BlockchainProcessor.java b/src/brs/BlockchainProcessor.java index 35d642dbc..afc2cd3f3 100644 --- a/src/brs/BlockchainProcessor.java +++ b/src/brs/BlockchainProcessor.java @@ -23,7 +23,7 @@ enum Event { int getMinRollbackHeight(); - void processPeerBlock(JSONObject request) throws BurstException; + void processPeerBlock(JSONObject request, Peer peer) throws BurstException; void fullReset(); diff --git a/src/brs/BlockchainProcessorImpl.java b/src/brs/BlockchainProcessorImpl.java index 33e07afce..47e72784f 100644 --- a/src/brs/BlockchainProcessorImpl.java +++ b/src/brs/BlockchainProcessorImpl.java @@ -20,7 +20,6 @@ import brs.statistics.StatisticsManagerImpl; import brs.services.AccountService; import brs.transactionduplicates.TransactionDuplicatesCheckerImpl; -import brs.transactionduplicates.TransactionDuplicationResult; import brs.unconfirmedtransactions.UnconfirmedTransactionStore; import brs.util.ThreadPool; @@ -32,11 +31,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; import java.util.LinkedList; import java.util.List; -import java.util.Map; -import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import java.util.concurrent.Semaphore; @@ -744,10 +740,10 @@ public int getMinRollbackHeight() { } @Override - public void processPeerBlock(JSONObject request) throws BurstException { + public void processPeerBlock(JSONObject request, Peer peer) throws BurstException { Block newBlock = Block.parseBlock(request, blockchain.getHeight()); if (newBlock == null) { - logger.debug("Peer has announced an unprocessable block."); + logger.debug("Peer {} has announced an unprocessable block.", peer.getPeerAddress()); return; } /* @@ -760,10 +756,9 @@ public void processPeerBlock(JSONObject request) throws BurstException { newBlock.setByteLength(newBlock.toString().length()); blockService.calculateBaseTarget(newBlock, chainblock); downloadCache.addBlock(newBlock); - logger.debug("Added from Anounce: Id: " +newBlock.getId()+" Height: "+newBlock.getHeight()); + logger.debug("Peer {} added block from Announce: Id: {} Height: {}", peer.getPeerAddress(), newBlock.getId(), newBlock.getHeight()); } else { - logger.debug("Peer sent us block: " + newBlock.getPreviousBlockId() - + " that does not match our chain."); + logger.debug("Peer {} sent us block: {} which is not the follow-up block for {}", peer.getPeerAddress(), newBlock.getPreviousBlockId(), chainblock.getId()); } } diff --git a/src/brs/peer/ProcessBlock.java b/src/brs/peer/ProcessBlock.java index bf79d7d33..2d8cdf5ac 100644 --- a/src/brs/peer/ProcessBlock.java +++ b/src/brs/peer/ProcessBlock.java @@ -41,7 +41,7 @@ public JSONStreamAware processRequest(JSONObject request, Peer peer) { // when loading blockchain from scratch return NOT_ACCEPTED; } - blockchainProcessor.processPeerBlock(request); + blockchainProcessor.processPeerBlock(request, peer); return ACCEPTED; } catch (BurstException|RuntimeException e) {