Skip to content
This repository has been archived by the owner on Aug 23, 2020. It is now read-only.

Commit

Permalink
Integration of new tip selection and cleanup of tipsManager (#785)
Browse files Browse the repository at this point in the history
* Integration of new tip selection and cleanup of tipsManager

* inject dependencies to tipselector appropriately

* added missing TipsSolidifier file

* Avoid throwing raw exception types.
Remove final.
  • Loading branch information
alon-e authored and GalRogozinski committed Jun 12, 2018
1 parent cbf7ebc commit afbf8b2
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 606 deletions.
30 changes: 23 additions & 7 deletions src/main/java/com/iota/iri/Iota.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package com.iota.iri;

import com.iota.iri.conf.Configuration;
import com.iota.iri.controllers.*;
import com.iota.iri.controllers.TipsViewModel;
import com.iota.iri.controllers.TransactionViewModel;
import com.iota.iri.hash.SpongeFactory;
import com.iota.iri.model.Hash;
import com.iota.iri.network.Node;
import com.iota.iri.network.TransactionRequester;
import com.iota.iri.network.UDPReceiver;
import com.iota.iri.network.replicator.Replicator;
import com.iota.iri.service.TipsManager;
import com.iota.iri.service.TipsSolidifier;
import com.iota.iri.service.tipselection.*;
import com.iota.iri.service.tipselection.impl.*;
import com.iota.iri.storage.*;
import com.iota.iri.storage.rocksDB.RocksDBPersistenceProvider;
import com.iota.iri.utils.Pair;
Expand All @@ -19,6 +22,7 @@
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.security.SecureRandom;
import java.util.List;

/**
Expand All @@ -31,7 +35,7 @@ public class Iota {
public final Milestone milestone;
public final Tangle tangle;
public final TransactionValidator transactionValidator;
public final TipsManager tipsManager;
public final TipsSolidifier tipsSolidifier;
public final TransactionRequester transactionRequester;
public final Node node;
public final UDPReceiver udpReceiver;
Expand All @@ -40,6 +44,7 @@ public class Iota {
public final Hash coordinator;
public final TipsViewModel tipsViewModel;
public final MessageQ messageQ;
public final TipSelector tipsSelector;

public final boolean testnet;
public final int maxPeers;
Expand All @@ -60,6 +65,8 @@ public Iota(Configuration configuration) throws IOException {
long snapshotTimestamp = configuration.longNum(Configuration.DefaultConfSettings.SNAPSHOT_TIME);
int milestoneStartIndex = configuration.integer(Configuration.DefaultConfSettings.MILESTONE_START_INDEX);
int numKeysMilestone = configuration.integer(Configuration.DefaultConfSettings.NUMBER_OF_KEYS_IN_A_MILESTONE);
double alpha = configuration.doubling(Configuration.DefaultConfSettings.TIPSELECTION_ALPHA.name());

boolean dontValidateMilestoneSig = configuration.booling(Configuration.DefaultConfSettings
.DONT_VALIDATE_TESTNET_MILESTONE_SIG);
int transactionPacketSize = configuration.integer(Configuration.DefaultConfSettings.TRANSACTION_PACKET_SIZE);
Expand Down Expand Up @@ -93,8 +100,8 @@ public Iota(Configuration configuration) throws IOException {
replicator = new Replicator(node, tcpPort, maxPeers, testnet, transactionPacketSize);
udpReceiver = new UDPReceiver(udpPort, node, configuration.integer(Configuration.DefaultConfSettings.TRANSACTION_PACKET_SIZE));
ledgerValidator = new LedgerValidator(tangle, milestone, transactionRequester, messageQ);
tipsManager = new TipsManager(tangle, ledgerValidator, transactionValidator, tipsViewModel, milestone,
maxTipSearchDepth, messageQ, testnet, milestoneStartIndex);
tipsSolidifier = new TipsSolidifier(tangle, transactionValidator, tipsViewModel);
tipsSelector = createTipSelector(milestoneStartIndex, alpha);
}

public void init() throws Exception {
Expand All @@ -113,7 +120,7 @@ public void init() throws Exception {
}
milestone.init(SpongeFactory.Mode.CURLP27, ledgerValidator, revalidate);
transactionValidator.init(testnet, configuration.integer(Configuration.DefaultConfSettings.MWM));
tipsManager.init();
tipsSolidifier.init();
transactionRequester.init(configuration.doubling(Configuration.DefaultConfSettings.P_REMOVE_REQUEST.name()));
udpReceiver.init();
replicator.init();
Expand Down Expand Up @@ -147,7 +154,7 @@ private void rescan_db() throws Exception {

public void shutdown() throws Exception {
milestone.shutDown();
tipsManager.shutdown();
tipsSolidifier.shutdown();
node.shutdown();
udpReceiver.shutdown();
replicator.shutdown();
Expand Down Expand Up @@ -190,4 +197,13 @@ private void initializeTangle() {
tangle.addPersistenceProvider(new ZmqPublishProvider(messageQ));
}
}

private TipSelector createTipSelector(int milestoneStartIndex, double alpha) {
EntryPointSelector entryPointSelector = new EntryPointSelectorImpl(tangle, milestone, testnet, milestoneStartIndex);
RatingCalculator ratingCalculator = new CumulativeWeightCalculator(tangle);
TailFinder tailFinder = new TailFinderImpl(tangle);
Walker walker = new WalkerAlpha(alpha, new SecureRandom(), tangle, messageQ, tailFinder);
return new TipSelectorImpl(tangle, ledgerValidator, transactionValidator, entryPointSelector, ratingCalculator,
walker, milestone, maxTipSearchDepth);
}
}
93 changes: 28 additions & 65 deletions src/main/java/com/iota/iri/service/API.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
Expand Down Expand Up @@ -287,26 +286,18 @@ private AbstractResponse process(final String requestString, InetSocketAddress s
return getTipsStatement();
}
case "getTransactionsToApprove": {
if (invalidSubtangleStatus()) {
return ErrorResponse
.create("This operations cannot be executed: The subtangle has not been updated yet.");
}

final String reference = request.containsKey("reference") ? getParameterAsStringAndValidate(request,"reference", HASH_SIZE) : null;
final Optional<Hash> reference = request.containsKey("reference") ?
Optional.of(new Hash (getParameterAsStringAndValidate(request,"reference", HASH_SIZE)))
: Optional.empty();
final int depth = getParameterAsInt(request, "depth");
if(depth < 0 || (reference == null && depth == 0)) {
if (depth < 0 || depth > instance.tipsSelector.getMaxDepth()) {
return ErrorResponse.create("Invalid depth input");
}
int numWalks = request.containsKey("numWalks") ? getParameterAsInt(request,"numWalks") : 1;
if(numWalks < minRandomWalks) {
numWalks = minRandomWalks;
}

try {
final Hash[] tips = getTransactionToApproveStatement(depth, reference, numWalks);
if(tips == null) {
return ErrorResponse.create("The subtangle is not solid");
}
return GetTransactionsToApproveResponse.create(tips[0], tips[1]);
List<Hash> tips = getTransactionToApproveStatement(depth, reference);
return GetTransactionsToApproveResponse.create(tips.get(0), tips.get(1));

} catch (RuntimeException e) {
log.info("Tip selection failed: " + e.getLocalizedMessage());
return ErrorResponse.create(e.getLocalizedMessage());
Expand Down Expand Up @@ -587,57 +578,29 @@ public static void incEllapsedTime_getTxToApprove(long ellapsedTime) {
ellapsedTime_getTxToApprove += ellapsedTime;
}

public synchronized Hash[] getTransactionToApproveStatement(int depth, final String reference, final int numWalks) throws Exception {
int tipsToApprove = 2;
Hash[] tips = new Hash[tipsToApprove];
final SecureRandom random = new SecureRandom();
final int randomWalkCount = numWalks > maxRandomWalks || numWalks < 1 ? maxRandomWalks:numWalks;
Hash referenceHash = null;
int maxDepth = instance.tipsManager.getMaxDepth();
if (depth > maxDepth) {
depth = maxDepth;
public synchronized List<Hash> getTransactionToApproveStatement(int depth, Optional<Hash> reference) throws Exception {

if (invalidSubtangleStatus()) {
throw new IllegalStateException("This operations cannot be executed: The subtangle has not been updated yet.");
}
if(reference != null) {
referenceHash = new Hash(reference);
if (!TransactionViewModel.exists(instance.tangle, referenceHash)) {
throw new RuntimeException(REFERENCE_TRANSACTION_NOT_FOUND);
} else {
TransactionViewModel transactionViewModel = TransactionViewModel.fromHash(instance.tangle, referenceHash);
if (transactionViewModel.snapshotIndex() != 0
&& transactionViewModel.snapshotIndex() < instance.milestone.latestSolidSubtangleMilestoneIndex - depth) {
throw new RuntimeException(REFERENCE_TRANSACTION_TOO_OLD);
}
}

List<Hash> tips = instance.tipsSelector.getTransactionsToApprove(depth, reference);

if (log.isDebugEnabled()) {
gatherStatisticsOnTipSelection();
}

instance.milestone.latestSnapshot.rwlock.readLock().lock();
try {
Set<Hash> visitedHashes = new HashSet<>();
Map<Hash, Long> diff = new HashMap<>();
for (int i = 0; i < tipsToApprove; i++) {
tips[i] = instance.tipsManager.transactionToApprove(visitedHashes, diff, referenceHash, tips[0], depth, randomWalkCount, random);
//update world view, so next tips selected will be inter-consistent
if (tips[i] == null || !instance.ledgerValidator.updateDiff(visitedHashes, diff, tips[i])) {
return null;
}
}
API.incCounter_getTxToApprove();
if ((getCounter_getTxToApprove() % 100) == 0) {
String sb = "Last 100 getTxToApprove consumed " +
API.getEllapsedTime_getTxToApprove() / 1000000000L +
" seconds processing time.";
log.info(sb);
counter_getTxToApprove = 0;
ellapsedTime_getTxToApprove = 0L;
}
return tips;
}

if (instance.ledgerValidator.checkConsistency(Arrays.asList(tips))) {
return tips;
}
} finally {
instance.milestone.latestSnapshot.rwlock.readLock().unlock();
private void gatherStatisticsOnTipSelection() {
API.incCounter_getTxToApprove();
if ((getCounter_getTxToApprove() % 100) == 0) {
String sb = "Last 100 getTxToApprove consumed " + API.getEllapsedTime_getTxToApprove() / 1000000000L + " seconds processing time.";
log.debug(sb);
counter_getTxToApprove = 0;
ellapsedTime_getTxToApprove = 0L;
}
throw new RuntimeException("inconsistent tips pair selected");
}

private synchronized AbstractResponse getTipsStatement() throws Exception {
Expand Down Expand Up @@ -1113,7 +1076,7 @@ public void shutDown() {

//only available on testnet
private synchronized void storeMessageStatement(final String address, final String message) throws Exception {
final Hash[] txToApprove = getTransactionToApproveStatement(3, null, 5);
final List<Hash> txToApprove = getTransactionToApproveStatement(3, Optional.empty());

final int txMessageSize = TransactionViewModel.SIGNATURE_MESSAGE_FRAGMENT_TRINARY_SIZE / 3;

Expand Down Expand Up @@ -1173,7 +1136,7 @@ private synchronized void storeMessageStatement(final String address, final Stri
transactions = transactions.stream().map(tx -> StringUtils.rightPad(tx + bundleHash, TRYTES_SIZE, '9')).collect(Collectors.toList());

// do pow
List<String> powResult = attachToTangleStatement(txToApprove[0], txToApprove[1], 9, transactions);
List<String> powResult = attachToTangleStatement(txToApprove.get(0), txToApprove.get(1), 9, transactions);
broadcastTransactionStatement(powResult);
}
}
Loading

0 comments on commit afbf8b2

Please sign in to comment.