diff --git a/src/main/java/com/iota/iri/service/tipselection/RatingCalculator.java b/src/main/java/com/iota/iri/service/tipselection/RatingCalculator.java index a99f8b01b1..8eeabdcca6 100644 --- a/src/main/java/com/iota/iri/service/tipselection/RatingCalculator.java +++ b/src/main/java/com/iota/iri/service/tipselection/RatingCalculator.java @@ -1,8 +1,8 @@ package com.iota.iri.service.tipselection; +import java.util.Map; + import com.iota.iri.model.Hash; -import com.iota.iri.model.HashId; -import com.iota.iri.utils.collections.interfaces.UnIterableMap; /** * Calculates the rating for a sub graph @@ -18,9 +18,9 @@ public interface RatingCalculator { * </p> * * @param entryPoint Transaction hash of a selected entry point. - * @return Map of ratings for each transaction that references entryPoint. + * @return Map of ratings for each transaction that references entryPoint. * @throws Exception If DB fails to retrieve transactions */ - UnIterableMap<HashId, Integer> calculate(Hash entryPoint) throws Exception; + Map<Hash, Integer> calculate(Hash entryPoint) throws Exception; } diff --git a/src/main/java/com/iota/iri/service/tipselection/Walker.java b/src/main/java/com/iota/iri/service/tipselection/Walker.java index a06d4d7e65..116335aa88 100644 --- a/src/main/java/com/iota/iri/service/tipselection/Walker.java +++ b/src/main/java/com/iota/iri/service/tipselection/Walker.java @@ -1,8 +1,8 @@ package com.iota.iri.service.tipselection; +import java.util.Map; + import com.iota.iri.model.Hash; -import com.iota.iri.model.HashId; -import com.iota.iri.utils.collections.interfaces.UnIterableMap; /** * Walks the tangle from an entry point towards tips @@ -24,6 +24,6 @@ public interface Walker { * @return Transaction hash of tip. * @throws Exception If DB fails to retrieve transactions */ - Hash walk(Hash entryPoint, UnIterableMap<HashId, Integer> ratings, WalkValidator walkValidator) throws Exception; + Hash walk(Hash entryPoint, Map<Hash, Integer> ratings, WalkValidator walkValidator) throws Exception; } diff --git a/src/main/java/com/iota/iri/service/tipselection/impl/CumulativeWeightCalculator.java b/src/main/java/com/iota/iri/service/tipselection/impl/CumulativeWeightCalculator.java index a788e6fc0f..d3416b570a 100644 --- a/src/main/java/com/iota/iri/service/tipselection/impl/CumulativeWeightCalculator.java +++ b/src/main/java/com/iota/iri/service/tipselection/impl/CumulativeWeightCalculator.java @@ -1,43 +1,37 @@ package com.iota.iri.service.tipselection.impl; +import java.util.ArrayDeque; +import java.util.Collection; +import java.util.Collections; +import java.util.Deque; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + import com.iota.iri.controllers.ApproveeViewModel; import com.iota.iri.controllers.TransactionViewModel; import com.iota.iri.model.Hash; -import com.iota.iri.model.HashId; -import com.iota.iri.model.HashPrefix; import com.iota.iri.service.snapshot.SnapshotProvider; import com.iota.iri.service.tipselection.RatingCalculator; -import com.iota.iri.utils.collections.impl.TransformingBoundedHashSet; import com.iota.iri.storage.Tangle; -import com.iota.iri.utils.collections.impl.TransformingMap; -import com.iota.iri.utils.collections.interfaces.BoundedSet; -import com.iota.iri.utils.collections.interfaces.UnIterableMap; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.SetUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.*; /** - * Implementation of {@link RatingCalculator} that calculates the cumulative weight - * for each transaction referencing {@code entryPoint}. <br> - * Used to create a weighted random walks. - * - * @see <a href="cumulative.md">https://github.com/alongalky/iota-docs/blob/master/cumulative.md</a> + * Implementation of {@link RatingCalculator} that calculates the cumulative weight + * Calculates the weight recursively/on the fly for each transaction referencing {@code entryPoint}. <br> + * Works using DFS search for new hashes and a BFS calculation. + * Uses cached values to prevent double database lookup for approvers */ -public class CumulativeWeightCalculator implements RatingCalculator{ - - private static final Logger log = LoggerFactory.getLogger(CumulativeWeightCalculator.class); - private static final int MAX_FUTURE_SET_SIZE = 5000; +public class CumulativeWeightCalculator implements RatingCalculator { - public final Tangle tangle; + private final Tangle tangle; private final SnapshotProvider snapshotProvider; /** * Constructor for Cumulative Weight Calculator + * * @param tangle Tangle object which acts as a database interface - * @param snapshotProvider acceses ledger's snapshots + * @param snapshotProvider accesses ledger's snapshots */ public CumulativeWeightCalculator(Tangle tangle, SnapshotProvider snapshotProvider) { this.tangle = tangle; @@ -45,128 +39,118 @@ public CumulativeWeightCalculator(Tangle tangle, SnapshotProvider snapshotProvid } @Override - public UnIterableMap<HashId, Integer> calculate(Hash entryPoint) throws Exception { - log.debug("Start calculating cw starting with tx hash {}", entryPoint); - - LinkedHashSet<Hash> txHashesToRate = sortTransactionsInTopologicalOrder(entryPoint); - return calculateCwInOrder(txHashesToRate); + public Map<Hash, Integer> calculate(Hash entryPoint) throws Exception { + Map<Hash, Integer> hashWeightMap = calculateRatingDfs(entryPoint); + + return hashWeightMap; } + + private Map<Hash, Integer> calculateRatingDfs(Hash entryPoint) throws Exception { + TransactionViewModel tvm = TransactionViewModel.fromHash(tangle, entryPoint); + int depth = tvm.snapshotIndex() > 0 + ? snapshotProvider.getLatestSnapshot().getIndex() - tvm.snapshotIndex() + 1 + : 1; - //Uses DFS algorithm to sort - private LinkedHashSet<Hash> sortTransactionsInTopologicalOrder(Hash startTx) throws Exception { - LinkedHashSet<Hash> sortedTxs = new LinkedHashSet<>(); - Deque<Hash> stack = new ArrayDeque<>(); - Map<Hash, Collection<Hash>> txToDirectApprovers = new HashMap<>(); + // Estimated capacity per depth, assumes 5 minute gap in between milestones, at 3tps + Map<Hash, Integer> hashWeightMap = createTxHashToCumulativeWeightMap( 5 * 60 * 3 * depth); + + Map<Hash, Set<Hash>> txToDirectApprovers = new HashMap<>(); - stack.push(startTx); - while (CollectionUtils.isNotEmpty(stack)) { - Hash txHash = stack.peek(); - if (!sortedTxs.contains(txHash)) { - Collection<Hash> appHashes = getTxDirectApproversHashes(txHash, txToDirectApprovers); - if (CollectionUtils.isNotEmpty(appHashes)) { - Hash txApp = getAndRemoveApprover(appHashes); - stack.push(txApp); - continue; + Deque<Hash> stack = new ArrayDeque<>(); + stack.addAll(getTxDirectApproversHashes(entryPoint, txToDirectApprovers)); + + while (!stack.isEmpty()) { + Hash txHash = stack.pollLast(); + + Set<Hash> approvers = getTxDirectApproversHashes(txHash, txToDirectApprovers); + + // If its empty, its a tip! + if (approvers.isEmpty()) { + hashWeightMap.put(txHash, 1); + + // Else we go deeper + } else { + // Add all approvers, given we didnt go there + for (Hash h : approvers) { + if (!hashWeightMap.containsKey(h)) { + stack.add(h); + } } - } - else { - stack.pop(); - continue; - } - sortedTxs.add(txHash); + + // Add the tx to the approvers list to count itself as +1 weight, preventing self-referencing + approvers.add(txHash); + + // calculate and add rating. Naturally the first time all approvers need to be looked up. Then its cached. + hashWeightMap.put(txHash, getRating(approvers, txToDirectApprovers)); + } } - return sortedTxs; + // If we have a self-reference, its already added, otherwise we save a big calculation + if (!hashWeightMap.containsKey(entryPoint)) { + hashWeightMap.put(entryPoint, hashWeightMap.size() + 1); + } + return hashWeightMap; } - private Hash getAndRemoveApprover(Collection<Hash> appHashes) { - Iterator<Hash> hashIterator = appHashes.iterator(); - Hash txApp = hashIterator.next(); - hashIterator.remove(); - return txApp; - } + /** + * Gets the rating of a set, calculated by checking its approvers + * + * @param startingSet All approvers of a certain hash, including the hash itself. + * Should always start with at least 1 hash. + * @param txToDirectApproversCache The cache of approvers, used to prevent double db lookups + * @return The weight, or rating, of the starting hash + * @throws Exception If we can't get the approvers + */ + private int getRating(Set<Hash> startingSet, Map<Hash, Set<Hash>> txToDirectApproversCache) throws Exception { + Deque<Hash> stack = new ArrayDeque<>(startingSet); + while (!stack.isEmpty()) { + Set<Hash> approvers = getTxDirectApproversHashes(stack.pollLast(), txToDirectApproversCache); + for (Hash hash : approvers) { + if (startingSet.add(hash)) { + stack.add(hash); + } + } + } - private Collection<Hash> getTxDirectApproversHashes(Hash txHash, Map<Hash, Collection<Hash>> txToDirectApprovers) + return startingSet.size(); + } + + /** + * Finds the approvers of a transaction, and adds it to the txToDirectApprovers map if they weren't there yet. + * + * @param txHash The tx we find the approvers of + * @param txToDirectApprovers The map we look in, and add to + * @param fallback The map we check in before going in the database, can be <code>null</code> + * @return A set with the direct approvers of the given hash + * @throws Exception + */ + private Set<Hash> getTxDirectApproversHashes(Hash txHash, Map<Hash, Set<Hash>> txToDirectApprovers) throws Exception { - Collection<Hash> txApprovers = txToDirectApprovers.get(txHash); + + Set<Hash> txApprovers = txToDirectApprovers.get(txHash); if (txApprovers == null) { ApproveeViewModel approvers = ApproveeViewModel.load(tangle, txHash); - Collection<Hash> appHashes = CollectionUtils.emptyIfNull(approvers.getHashes()); + Collection<Hash> appHashes; + if (approvers == null || approvers.getHashes() == null) { + appHashes = Collections.emptySet(); + } else { + appHashes = approvers.getHashes(); + } + txApprovers = new HashSet<>(appHashes.size()); for (Hash appHash : appHashes) { - //if not genesis (the tx that confirms itself) + // if not genesis (the tx that confirms itself) if (!snapshotProvider.getInitialSnapshot().hasSolidEntryPoint(appHash)) { txApprovers.add(appHash); } } txToDirectApprovers.put(txHash, txApprovers); } - return txApprovers; + + return new HashSet<Hash>(txApprovers); } - - //must specify using LinkedHashSet since Java has no interface that guarantees uniqueness and insertion order - private UnIterableMap<HashId, Integer> calculateCwInOrder(LinkedHashSet<Hash> txsToRate) throws Exception { - UnIterableMap<HashId, Set<HashId>> txHashToApprovers = createTxHashToApproversPrefixMap(); - UnIterableMap<HashId, Integer> txHashToCumulativeWeight = createTxHashToCumulativeWeightMap(txsToRate.size()); - - Iterator<Hash> txHashIterator = txsToRate.iterator(); - while (txHashIterator.hasNext()) { - if (Thread.interrupted()) { - throw new InterruptedException(); - } - Hash txHash = txHashIterator.next(); - txHashToCumulativeWeight = updateCw(txHashToApprovers, txHashToCumulativeWeight, txHash); - txHashToApprovers = updateApproversAndReleaseMemory(txHashToApprovers, txHash); - txHashIterator.remove(); - } - return txHashToCumulativeWeight; - } - - - private UnIterableMap<HashId, Set<HashId>> updateApproversAndReleaseMemory(UnIterableMap<HashId, - Set<HashId>> txHashToApprovers, Hash txHash) throws Exception { - Set<HashId> approvers = SetUtils.emptyIfNull(txHashToApprovers.get(txHash)); - - TransactionViewModel transactionViewModel = TransactionViewModel.fromHash(tangle, txHash); - Hash trunkHash = transactionViewModel.getTrunkTransactionHash(); - Hash branchHash = transactionViewModel.getBranchTransactionHash(); - - Set<HashId> trunkApprovers = createApprovers(txHashToApprovers, txHash, approvers, trunkHash); - txHashToApprovers.put(trunkHash, trunkApprovers); - Set<HashId> branchApprovers = createApprovers(txHashToApprovers, txHash, approvers, branchHash); - txHashToApprovers.put(branchHash, branchApprovers); - - txHashToApprovers.remove(txHash); - - return txHashToApprovers; - } - - private Set<HashId> createApprovers(UnIterableMap<HashId, Set<HashId>> txHashToApprovers, HashId txHash, - Set<HashId> approvers, HashId trunkHash) { - Set<HashId> approverSet = createTransformingBoundedSet(approvers); - approverSet.addAll(CollectionUtils.emptyIfNull(txHashToApprovers.get(trunkHash))); - approverSet.add(txHash); - return approverSet; - } - - private static <T extends HashId> UnIterableMap<HashId, Integer> updateCw( - UnIterableMap<HashId, Set<T>> txHashToApprovers, UnIterableMap<HashId, Integer> txToCumulativeWeight, - Hash txHash) { - Set<T> approvers = txHashToApprovers.get(txHash); - int weight = CollectionUtils.emptyIfNull(approvers).size() + 1; - txToCumulativeWeight.put(txHash, weight); - return txToCumulativeWeight; - } - - private static UnIterableMap<HashId, Set<HashId>> createTxHashToApproversPrefixMap() { - return new TransformingMap<>(HashPrefix::createPrefix, null); - } - - private static UnIterableMap<HashId, Integer> createTxHashToCumulativeWeightMap(int size) { - return new TransformingMap<>(size, HashPrefix::createPrefix, null); - } - - private static BoundedSet<HashId> createTransformingBoundedSet(Collection<HashId> c) { - return new TransformingBoundedHashSet<>(c, MAX_FUTURE_SET_SIZE, HashPrefix::createPrefix); + + private static Map<Hash, Integer> createTxHashToCumulativeWeightMap(int size) { + return new HashMap<Hash, Integer>(size); //new TransformingMap<>(size, HashPrefix::createPrefix, null); } } diff --git a/src/main/java/com/iota/iri/service/tipselection/impl/RatingOne.java b/src/main/java/com/iota/iri/service/tipselection/impl/RatingOne.java index d6bcbe1349..162d90c492 100644 --- a/src/main/java/com/iota/iri/service/tipselection/impl/RatingOne.java +++ b/src/main/java/com/iota/iri/service/tipselection/impl/RatingOne.java @@ -1,14 +1,15 @@ package com.iota.iri.service.tipselection.impl; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; +import java.util.Queue; +import java.util.Set; + import com.iota.iri.controllers.ApproveeViewModel; import com.iota.iri.model.Hash; -import com.iota.iri.model.HashId; import com.iota.iri.service.tipselection.RatingCalculator; import com.iota.iri.storage.Tangle; -import com.iota.iri.utils.collections.impl.TransformingMap; -import com.iota.iri.utils.collections.interfaces.UnIterableMap; - -import java.util.*; /** * Implementation of <tt>RatingCalculator</tt> that gives a uniform rating of 1 to each transaction. @@ -23,8 +24,8 @@ public RatingOne(Tangle tangle) { } @Override - public UnIterableMap<HashId, Integer> calculate(Hash entryPoint) throws Exception { - UnIterableMap<HashId, Integer> rating = new TransformingMap<>(null, null); + public Map<Hash, Integer> calculate(Hash entryPoint) throws Exception { + Map<Hash, Integer> rating = new HashMap<>(); Queue<Hash> queue = new LinkedList<>(); queue.add(entryPoint); diff --git a/src/main/java/com/iota/iri/service/tipselection/impl/TipSelectorImpl.java b/src/main/java/com/iota/iri/service/tipselection/impl/TipSelectorImpl.java index 9cdc1d07b0..8393c184b6 100644 --- a/src/main/java/com/iota/iri/service/tipselection/impl/TipSelectorImpl.java +++ b/src/main/java/com/iota/iri/service/tipselection/impl/TipSelectorImpl.java @@ -1,18 +1,21 @@ package com.iota.iri.service.tipselection.impl; +import java.security.InvalidAlgorithmParameterException; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Optional; + import com.iota.iri.conf.TipSelConfig; import com.iota.iri.model.Hash; -import com.iota.iri.model.HashId; import com.iota.iri.service.ledger.LedgerService; import com.iota.iri.service.snapshot.SnapshotProvider; -import com.iota.iri.service.tipselection.*; +import com.iota.iri.service.tipselection.EntryPointSelector; +import com.iota.iri.service.tipselection.RatingCalculator; +import com.iota.iri.service.tipselection.TipSelector; +import com.iota.iri.service.tipselection.WalkValidator; +import com.iota.iri.service.tipselection.Walker; import com.iota.iri.storage.Tangle; -import com.iota.iri.utils.collections.interfaces.UnIterableMap; - -import java.security.InvalidAlgorithmParameterException; -import java.util.LinkedList; -import java.util.List; -import java.util.Optional; /** * Implementation of <tt>TipSelector</tt> that selects 2 tips, @@ -89,7 +92,7 @@ public List<Hash> getTransactionsToApprove(int depth, Optional<Hash> reference) //preparation Hash entryPoint = entryPointSelector.getEntryPoint(depth); - UnIterableMap<HashId, Integer> rating = ratingCalculator.calculate(entryPoint); + Map<Hash, Integer> rating = ratingCalculator.calculate(entryPoint); //random walk List<Hash> tips = new LinkedList<>(); @@ -117,7 +120,7 @@ public List<Hash> getTransactionsToApprove(int depth, Optional<Hash> reference) } } - private void checkReference(HashId reference, UnIterableMap<HashId, Integer> rating) + private void checkReference(Hash reference, Map<Hash, Integer> rating) throws InvalidAlgorithmParameterException { if (!rating.containsKey(reference)) { throw new InvalidAlgorithmParameterException(REFERENCE_TRANSACTION_TOO_OLD); diff --git a/src/main/java/com/iota/iri/service/tipselection/impl/WalkerAlpha.java b/src/main/java/com/iota/iri/service/tipselection/impl/WalkerAlpha.java index f2ae75d698..49fda10ad3 100644 --- a/src/main/java/com/iota/iri/service/tipselection/impl/WalkerAlpha.java +++ b/src/main/java/com/iota/iri/service/tipselection/impl/WalkerAlpha.java @@ -1,19 +1,24 @@ package com.iota.iri.service.tipselection.impl; +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Random; +import java.util.Set; +import java.util.stream.Collectors; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.iota.iri.conf.TipSelConfig; import com.iota.iri.controllers.ApproveeViewModel; import com.iota.iri.model.Hash; -import com.iota.iri.model.HashId; import com.iota.iri.service.tipselection.TailFinder; import com.iota.iri.service.tipselection.WalkValidator; import com.iota.iri.service.tipselection.Walker; import com.iota.iri.storage.Tangle; -import com.iota.iri.utils.collections.interfaces.UnIterableMap; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.*; -import java.util.stream.Collectors; /** * Implementation of <tt>Walker</tt> that performs a weighted random walk @@ -64,7 +69,7 @@ public void setAlpha(double alpha) { } @Override - public Hash walk(Hash entryPoint, UnIterableMap<HashId, Integer> ratings, WalkValidator walkValidator) throws Exception { + public Hash walk(Hash entryPoint, Map<Hash, Integer> ratings, WalkValidator walkValidator) throws Exception { if (!walkValidator.isValid(entryPoint)) { throw new IllegalStateException("entry point failed consistency check: " + entryPoint.toString()); } @@ -88,7 +93,7 @@ public Hash walk(Hash entryPoint, UnIterableMap<HashId, Integer> ratings, WalkVa return traversedTails.getLast(); } - private Optional<Hash> selectApprover(Hash tailHash, UnIterableMap<HashId, Integer> ratings, WalkValidator walkValidator) throws Exception { + private Optional<Hash> selectApprover(Hash tailHash, Map<Hash, Integer> ratings, WalkValidator walkValidator) throws Exception { Set<Hash> approvers = getApprovers(tailHash); return findNextValidTail(ratings, approvers, walkValidator); } @@ -98,7 +103,7 @@ private Set<Hash> getApprovers(Hash tailHash) throws Exception { return approveeViewModel.getHashes(); } - private Optional<Hash> findNextValidTail(UnIterableMap<HashId, Integer> ratings, Set<Hash> approvers, WalkValidator walkValidator) throws Exception { + private Optional<Hash> findNextValidTail(Map<Hash, Integer> ratings, Set<Hash> approvers, WalkValidator walkValidator) throws Exception { Optional<Hash> nextTailHash = Optional.empty(); //select next tail to step to @@ -117,7 +122,7 @@ private Optional<Hash> findNextValidTail(UnIterableMap<HashId, Integer> ratings, return nextTailHash; } - private Optional<Hash> select(UnIterableMap<HashId, Integer> ratings, Set<Hash> approversSet) { + private Optional<Hash> select(Map<Hash, Integer> ratings, Set<Hash> approversSet) { //filter based on tangle state when starting the walk List<Hash> approvers = approversSet.stream().filter(ratings::containsKey).collect(Collectors.toList()); diff --git a/src/test/java/com/iota/iri/service/tipselection/impl/CumulativeWeightCalculatorTest.java b/src/test/java/com/iota/iri/service/tipselection/impl/CumulativeWeightCalculatorTest.java index 4f0a1caad8..c2c4cf7249 100644 --- a/src/test/java/com/iota/iri/service/tipselection/impl/CumulativeWeightCalculatorTest.java +++ b/src/test/java/com/iota/iri/service/tipselection/impl/CumulativeWeightCalculatorTest.java @@ -1,6 +1,29 @@ package com.iota.iri.service.tipselection.impl; +import static com.iota.iri.TransactionTestUtils.getTransactionHash; +import static com.iota.iri.TransactionTestUtils.getTransactionTrits; +import static com.iota.iri.TransactionTestUtils.getTransactionTritsWithTrunkAndBranch; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.iota.iri.conf.MainnetConfig; import com.iota.iri.controllers.ApproveeViewModel; import com.iota.iri.controllers.TransactionViewModel; @@ -9,20 +32,10 @@ import com.iota.iri.model.HashId; import com.iota.iri.service.snapshot.SnapshotProvider; import com.iota.iri.service.snapshot.impl.SnapshotProviderImpl; +import com.iota.iri.service.tipselection.RatingCalculator; import com.iota.iri.storage.Tangle; import com.iota.iri.storage.rocksDB.RocksDBPersistenceProvider; -import com.iota.iri.utils.collections.interfaces.UnIterableMap; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.*; -import static com.iota.iri.TransactionTestUtils.*; public class CumulativeWeightCalculatorTest { private static final TemporaryFolder dbFolder = new TemporaryFolder(); @@ -31,7 +44,7 @@ public class CumulativeWeightCalculatorTest { "tx%d cumulative weight is not as expected"; private static Tangle tangle; private static SnapshotProvider snapshotProvider; - private static CumulativeWeightCalculator cumulativeWeightCalculator; + private static RatingCalculator cumulativeWeightCalculator; private final Logger log = LoggerFactory.getLogger(this.getClass()); @AfterClass @@ -71,7 +84,7 @@ public void testCalculateCumulativeWeight() throws Exception { transaction2.store(tangle, snapshotProvider.getInitialSnapshot()); transaction3.store(tangle, snapshotProvider.getInitialSnapshot()); transaction4.store(tangle, snapshotProvider.getInitialSnapshot()); - UnIterableMap<HashId, Integer> txToCw = cumulativeWeightCalculator.calculate(transaction.getHash()); + Map<Hash, Integer> txToCw = cumulativeWeightCalculator.calculate(transaction.getHash()); Assert.assertEquals(String.format(TX_CUMULATIVE_WEIGHT_IS_NOT_AS_EXPECTED_FORMAT, 4), 1, txToCw.get(transaction4.getHash()).intValue()); @@ -102,7 +115,7 @@ public void testCalculateCumulativeWeightDiamond() throws Exception { log.debug("printing transaction in diamond shape \n {} \n{} {}\n {}", transaction.getHash(), transaction1.getHash(), transaction2.getHash(), transaction3.getHash()); - UnIterableMap<HashId, Integer> txToCw = cumulativeWeightCalculator.calculate(transaction.getHash()); + Map<Hash, Integer> txToCw = cumulativeWeightCalculator.calculate(transaction.getHash()); Assert.assertEquals(String.format(TX_CUMULATIVE_WEIGHT_IS_NOT_AS_EXPECTED_FORMAT, 3), 1, txToCw.get(transaction3.getHash()) @@ -138,7 +151,7 @@ public void testCalculateCumulativeWeightLinear() throws Exception { log.info(String.format("Linear ordered hashes from tip %.4s, %.4s, %.4s, %.4s, %.4s", transaction4.getHash(), transaction3.getHash(), transaction2.getHash(), transaction1.getHash(), transaction.getHash())); - UnIterableMap<HashId, Integer> txToCw = cumulativeWeightCalculator.calculate(transaction.getHash()); + Map<Hash, Integer> txToCw = cumulativeWeightCalculator.calculate(transaction.getHash()); Assert.assertEquals(String.format(TX_CUMULATIVE_WEIGHT_IS_NOT_AS_EXPECTED_FORMAT, 4), @@ -183,7 +196,7 @@ public void testCalculateCumulativeWeight2() throws Exception { transaction.getHash(), transaction1.getHash(), transaction2.getHash(), transaction3.getHash(), transaction4, transaction5, transaction6); - UnIterableMap<HashId, Integer> txToCw = cumulativeWeightCalculator.calculate(transaction.getHash()); + Map<Hash, Integer> txToCw = cumulativeWeightCalculator.calculate(transaction.getHash()); Assert.assertEquals(String.format(TX_CUMULATIVE_WEIGHT_IS_NOT_AS_EXPECTED_FORMAT, 6), 1, txToCw.get(transaction6.getHash()).intValue()); @@ -221,7 +234,7 @@ public void cwCalculationSameAsLegacy() throws Exception { } Map<HashId, Set<HashId>> ratings = new HashMap<>(); updateApproversRecursively(hashes[0], ratings, new HashSet<>()); - UnIterableMap<HashId, Integer> txToCw = cumulativeWeightCalculator.calculate(hashes[0]); + Map<Hash, Integer> txToCw = cumulativeWeightCalculator.calculate(hashes[0]); Assert.assertEquals("missing txs from new calculation", ratings.size(), txToCw.size()); ratings.forEach((hash, weight) -> { @@ -241,7 +254,7 @@ public void testTangleWithCircle() throws Exception { transaction.store(tangle, snapshotProvider.getInitialSnapshot()); - UnIterableMap<HashId, Integer> txToCw = cumulativeWeightCalculator.calculate(transaction.getHash()); + Map<Hash, Integer> txToCw = cumulativeWeightCalculator.calculate(transaction.getHash()); Assert.assertEquals("There should be only one tx in the map", 1, txToCw.size()); Assert.assertEquals("The circle raised the weight", 1, txToCw.get(randomTransactionHash).intValue()); } @@ -268,7 +281,9 @@ public void testTangleWithCircle2() throws Exception { //No infinite loop (which will probably result in an overflow exception) means test has passed } + // Ignored as we do not use HashId in CW, which leads to no more collisions from that. @Test + @Ignore public void testCollsionsInDiamondTangle() throws Exception { TransactionViewModel transaction, transaction1, transaction2, transaction3; transaction = new TransactionViewModel(getTransactionTrits(), getTransactionHash()); @@ -286,7 +301,7 @@ public void testCollsionsInDiamondTangle() throws Exception { log.debug("printing transaction in diamond shape \n {} \n{} {}\n {}", transaction.getHash(), transaction1.getHash(), transaction2.getHash(), transaction3.getHash()); - UnIterableMap<HashId, Integer> txToCw = cumulativeWeightCalculator.calculate(transaction.getHash()); + Map<Hash, Integer> txToCw = cumulativeWeightCalculator.calculate(transaction.getHash()); Assert.assertEquals(String.format(TX_CUMULATIVE_WEIGHT_IS_NOT_AS_EXPECTED_FORMAT, 3), 1, txToCw.get(transaction3.getHash()).intValue()); diff --git a/src/test/java/com/iota/iri/service/tipselection/impl/RatingOneTest.java b/src/test/java/com/iota/iri/service/tipselection/impl/RatingOneTest.java index 8edffdb5a7..6fb0451805 100644 --- a/src/test/java/com/iota/iri/service/tipselection/impl/RatingOneTest.java +++ b/src/test/java/com/iota/iri/service/tipselection/impl/RatingOneTest.java @@ -1,23 +1,25 @@ package com.iota.iri.service.tipselection.impl; +import static com.iota.iri.TransactionTestUtils.getTransactionHash; +import static com.iota.iri.TransactionTestUtils.getTransactionTrits; +import static com.iota.iri.TransactionTestUtils.getTransactionTritsWithTrunkAndBranch; + +import java.util.Map; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + import com.iota.iri.conf.MainnetConfig; import com.iota.iri.controllers.TransactionViewModel; -import com.iota.iri.model.HashId; +import com.iota.iri.model.Hash; import com.iota.iri.service.snapshot.SnapshotProvider; import com.iota.iri.service.snapshot.impl.SnapshotProviderImpl; import com.iota.iri.service.tipselection.RatingCalculator; import com.iota.iri.storage.Tangle; import com.iota.iri.storage.rocksDB.RocksDBPersistenceProvider; -import com.iota.iri.utils.collections.interfaces.UnIterableMap; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -import static com.iota.iri.TransactionTestUtils.getTransactionTrits; -import static com.iota.iri.TransactionTestUtils.getTransactionHash; -import static com.iota.iri.TransactionTestUtils.getTransactionTritsWithTrunkAndBranch; public class RatingOneTest { private static final TemporaryFolder dbFolder = new TemporaryFolder(); @@ -65,7 +67,7 @@ public void testCalculate() throws Exception { transaction2.store(tangle, snapshotProvider.getInitialSnapshot()); transaction3.store(tangle, snapshotProvider.getInitialSnapshot()); transaction4.store(tangle, snapshotProvider.getInitialSnapshot()); - UnIterableMap<HashId, Integer> rate = rating.calculate(transaction.getHash()); + Map<Hash, Integer> rate = rating.calculate(transaction.getHash()); Assert.assertEquals(TX_CUMULATIVE_WEIGHT_IS_NOT_AS_EXPECTED_FORMAT, 1, rate.get(transaction4.getHash()).intValue()); diff --git a/src/test/java/com/iota/iri/service/tipselection/impl/WalkerAlphaTest.java b/src/test/java/com/iota/iri/service/tipselection/impl/WalkerAlphaTest.java index 703aa70e2e..bbcf43b5b9 100644 --- a/src/test/java/com/iota/iri/service/tipselection/impl/WalkerAlphaTest.java +++ b/src/test/java/com/iota/iri/service/tipselection/impl/WalkerAlphaTest.java @@ -1,16 +1,8 @@ package com.iota.iri.service.tipselection.impl; -import com.iota.iri.conf.MainnetConfig; -import com.iota.iri.controllers.TransactionViewModel; -import com.iota.iri.model.Hash; -import com.iota.iri.model.HashId; -import com.iota.iri.service.snapshot.SnapshotProvider; -import com.iota.iri.service.snapshot.impl.SnapshotProviderImpl; -import com.iota.iri.service.tipselection.RatingCalculator; -import com.iota.iri.service.tipselection.TailFinder; -import com.iota.iri.storage.Tangle; -import com.iota.iri.storage.rocksDB.RocksDBPersistenceProvider; -import com.iota.iri.utils.collections.interfaces.UnIterableMap; +import static com.iota.iri.TransactionTestUtils.getTransactionHash; +import static com.iota.iri.TransactionTestUtils.getTransactionTrits; +import static com.iota.iri.TransactionTestUtils.getTransactionTritsWithTrunkAndBranch; import java.util.HashMap; import java.util.Map; @@ -26,9 +18,15 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static com.iota.iri.TransactionTestUtils.getTransactionTrits; -import static com.iota.iri.TransactionTestUtils.getTransactionHash; -import static com.iota.iri.TransactionTestUtils.getTransactionTritsWithTrunkAndBranch; +import com.iota.iri.conf.MainnetConfig; +import com.iota.iri.controllers.TransactionViewModel; +import com.iota.iri.model.Hash; +import com.iota.iri.service.snapshot.SnapshotProvider; +import com.iota.iri.service.snapshot.impl.SnapshotProviderImpl; +import com.iota.iri.service.tipselection.RatingCalculator; +import com.iota.iri.service.tipselection.TailFinder; +import com.iota.iri.storage.Tangle; +import com.iota.iri.storage.rocksDB.RocksDBPersistenceProvider; public class WalkerAlphaTest { private static final TemporaryFolder dbFolder = new TemporaryFolder(); @@ -83,7 +81,7 @@ public void testWalkEndsOnlyInRating() throws Exception { //calculate rating RatingCalculator ratingCalculator = new RatingOne(tangle); - UnIterableMap<HashId, Integer> rating = ratingCalculator.calculate(transaction.getHash()); + Map<Hash, Integer> rating = ratingCalculator.calculate(transaction.getHash()); //add 4 after the rating was calculated transaction4 = new TransactionViewModel(getTransactionTritsWithTrunkAndBranch(transaction.getHash(), @@ -120,7 +118,7 @@ public void showWalkDistributionAlphaHalf() throws Exception { //calculate rating RatingCalculator ratingCalculator = new RatingOne(tangle); - UnIterableMap<HashId, Integer> rating = ratingCalculator.calculate(transaction.getHash()); + Map<Hash, Integer> rating = ratingCalculator.calculate(transaction.getHash()); //set a higher rate for transaction2 rating.put(transaction2.getHash(), 10); @@ -163,7 +161,7 @@ public void showWalkDistributionAlphaZero() throws Exception { //calculate rating RatingCalculator ratingCalculator = new RatingOne(tangle); - UnIterableMap<HashId, Integer> rating = ratingCalculator.calculate(transaction.getHash()); + Map<Hash, Integer> rating = ratingCalculator.calculate(transaction.getHash()); //set a higher rate for transaction2 rating.put(transaction2.getHash(), 10); @@ -212,7 +210,7 @@ public void testWalk() throws Exception { //calculate rating RatingCalculator ratingCalculator = new RatingOne(tangle); - UnIterableMap<HashId, Integer> rating = ratingCalculator.calculate(transaction.getHash()); + Map<Hash, Integer> rating = ratingCalculator.calculate(transaction.getHash()); //reach the tips Hash tip = walker.walk(transaction.getHash(), rating, (o -> true)); @@ -239,7 +237,7 @@ public void testWalkDiamond() throws Exception { //calculate rating RatingCalculator ratingCalculator = new RatingOne(tangle); - UnIterableMap<HashId, Integer> rating = ratingCalculator.calculate(transaction.getHash()); + Map<Hash, Integer> rating = ratingCalculator.calculate(transaction.getHash()); //reach the tips Hash tip = walker.walk(transaction.getHash(), rating, (o -> true)); @@ -269,7 +267,7 @@ public void testWalkChain() throws Exception { //calculate rating RatingCalculator ratingCalculator = new RatingOne(tangle); - UnIterableMap<HashId, Integer> rating = ratingCalculator.calculate(transaction.getHash()); + Map<Hash, Integer> rating = ratingCalculator.calculate(transaction.getHash()); //reach the tips Hash tip = walker.walk(transaction.getHash(), rating, (o -> true));