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

Commit

Permalink
Merge branch 'release-v1.8.4'
Browse files Browse the repository at this point in the history
  • Loading branch information
Gal Rogozinski committed Jan 5, 2020
2 parents cff4f90 + 344b7d6 commit fa79533
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 41 deletions.
31 changes: 31 additions & 0 deletions changelog.txt
@@ -1,3 +1,34 @@
1.8.4

Hotfix: Ensure proper creation of solid entrypoints (#1702)

1.8.3

There is an edge case where IRI didn't account for a transaction that was shared between two distinct bundles.
Once it marked it as "counted" in one bundle, it was ignored for the next bundle. This lead to a corrupt ledger state.

Hotfix: Gyros - take transaction reattachments into account (#1699)

1.8.2

Change: The alpha value is now 0 by default, streamlining the tip selection process which will reduce memory and cpu load. This is done by skipping cumulative weight calculations. (Issue #1567)

Fix: correct data setting into Hash object (#1589)
Fix: Persistables merge and load functionality
Documentation: Fix broken link of online documentation (#1623)
Documentation: Update README.md (#1617)
Fix: always set the domain field of a neighbor (#1604)
Change: Use mocked SnapshotProvider (#1531)
Fix: Fixes regression introduced through the bundle validator refactor (#1588)
Documentation: Document Persistable and Indexable (#1169)
Feature: Adds progress bar and estimated time until the node is synced (#1575)
Change: Curl improvement
Change: Bundle validator refactor
Change: Use maven assembly plugin to create one jar with all dependencies (#1573)
Documentation: Document Persistence Provider (#1157)
Documentation: Updated links to official documentation (#1560)


1.8.1

- Feature: Improved CW Calculation (#1451)
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Expand Up @@ -5,7 +5,7 @@

<groupId>com.iota</groupId>
<artifactId>iri</artifactId>
<version>1.8.3</version>
<version>1.8.4</version>
<name>IRI</name>
<description>IOTA Reference Implementation</description>

Expand Down
Expand Up @@ -510,7 +510,7 @@ private void persistLocalSnapshot(SnapshotProvider snapshotProvider, Snapshot ne

/**
* <p>
* This method determines if a transaction is orphaned.
* This method determines if a transaction is orphaned when none of its approvers is confirmed by a milestone.
* </p>
* <p>
* Since there is no hard definition for when a transaction can be considered to be orphaned, we define orphaned in
Expand All @@ -522,14 +522,14 @@ private void persistLocalSnapshot(SnapshotProvider snapshotProvider, Snapshot ne
* a relatively safe way to determine if a subtangle "above" a transaction got orphaned.
* </p>
*
* @param tangle Tangle object which acts as a database interface
* @param transaction transaction that shall be checked
* @param referenceTransaction transaction that acts as a judge to the other transaction
* @param tangle Tangle object which acts as a database interface
* @param transaction transaction that shall be checked
* @param referenceTransaction transaction that acts as a judge to the other transaction
* @param processedTransactions transactions that were visited already while trying to determine the orphaned status
* @return true if the transaction got orphaned and false otherwise
* @throws SnapshotException if anything goes wrong while determining the orphaned status
*/
private boolean isOrphaned(Tangle tangle, TransactionViewModel transaction,
private boolean isProbablyOrphaned(Tangle tangle, TransactionViewModel transaction,
TransactionViewModel referenceTransaction, Set<Hash> processedTransactions) throws SnapshotException {

AtomicBoolean nonOrphanedTransactionFound = new AtomicBoolean(false);
Expand All @@ -553,29 +553,27 @@ private boolean isOrphaned(Tangle tangle, TransactionViewModel transaction,

/**
* <p>
* This method checks if a transaction is a solid entry point for the targetMilestone.
* </p>
* <p>
* A transaction is considered a solid entry point if it has non-orphaned approvers.
* We determine whether future milestones will approve {@param transactionHash}. This should aid in determining
* solid entry points.
* </p>
* <p>
* To check if the transaction has non-orphaned approvers we first check if any of its approvers got confirmed by a
* future milestone, since this is very cheap. If none of them got confirmed by another milestone we do the more
* expensive check from {@link #isOrphaned(Tangle, TransactionViewModel, TransactionViewModel, Set)}.
* expensive check from {@link #isProbablyOrphaned(Tangle, TransactionViewModel, TransactionViewModel, Set)}.
* </p>
* <p>
* Since solid entry points have a limited life time and to prevent potential problems due to temporary errors in
* the database, we assume that the checked transaction is a solid entry point if any error occurs while determining
* its status. This is a storage <=> reliability trade off, since the only bad effect of having too many solid entry
* points) is a bigger snapshot file.
* the database, we assume that the checked transaction is not orphaned if any error occurs while determining its
* status, thus adding solid entry points. This is a storage <=> reliability trade off, since the only bad effect of
* having too many solid entry points) is a bigger snapshot file.
* </p>
*
* @param tangle Tangle object which acts as a database interface
* @param tangle Tangle object which acts as a database interface
* @param transactionHash hash of the transaction that shall be checked
* @param targetMilestone milestone that is used as an anchor for our checks
* @return true if the transaction is a solid entry point and false otherwise
*/
private boolean isSolidEntryPoint(Tangle tangle, Hash transactionHash, MilestoneViewModel targetMilestone) {
private boolean isNotOrphaned(Tangle tangle, Hash transactionHash, MilestoneViewModel targetMilestone) {
Set<TransactionViewModel> unconfirmedApprovers = new HashSet<>();

try {
Expand All @@ -592,7 +590,7 @@ private boolean isSolidEntryPoint(Tangle tangle, Hash transactionHash, Milestone
Set<Hash> processedTransactions = new HashSet<>();
TransactionViewModel milestoneTransaction = TransactionViewModel.fromHash(tangle, targetMilestone.getHash());
for (TransactionViewModel unconfirmedApprover : unconfirmedApprovers) {
if (!isOrphaned(tangle, unconfirmedApprover, milestoneTransaction, processedTransactions)) {
if (!isProbablyOrphaned(tangle, unconfirmedApprover, milestoneTransaction, processedTransactions)) {
return true;
}
}
Expand All @@ -610,51 +608,66 @@ private boolean isSolidEntryPoint(Tangle tangle, Hash transactionHash, Milestone
* This method analyzes the old solid entry points and determines if they are still not orphaned.
* </p>
* <p>
* It simply iterates through the old solid entry points and checks them one by one. If an old solid entry point
* is found to still be relevant it is added to the passed in map.
* It simply iterates through the old solid entry points and checks them one by one. If an old solid entry point is
* found to still be relevant it is added to the passed in map.
* </p>
*
* @param tangle Tangle object which acts as a database interface
*
* @see #processNewSolidEntryPoints to understand the definition for solid entry points
* @param tangle Tangle object which acts as a database interface
* @param snapshotProvider data provider for the {@link Snapshot}s that are relevant for the node
* @param targetMilestone milestone that is used to generate the solid entry points
* @param targetMilestone milestone that is used to generate the solid entry points
* @param solidEntryPoints map that is used to collect the solid entry points
*/
private void processOldSolidEntryPoints(Tangle tangle, SnapshotProvider snapshotProvider,
MilestoneViewModel targetMilestone, Map<Hash, Integer> solidEntryPoints) {
MilestoneViewModel targetMilestone, Map<Hash, Integer> solidEntryPoints) throws SnapshotException {

ProgressLogger progressLogger = new IntervalProgressLogger(
"Taking local snapshot [analyzing old solid entry points]", log)
.start(snapshotProvider.getInitialSnapshot().getSolidEntryPoints().size());
try {
Snapshot initialSnapshot = snapshotProvider.getInitialSnapshot();
Map<Hash, Integer> orgSolidEntryPoints = initialSnapshot.getSolidEntryPoints();
for (Map.Entry<Hash, Integer> solidPoint : orgSolidEntryPoints.entrySet()) {
Hash hash = solidPoint.getKey();
int milestoneIndex = solidPoint.getValue();
if (!Hash.NULL_HASH.equals(hash)
&& targetMilestone.index() - milestoneIndex <= SOLID_ENTRY_POINT_LIFETIME
&& isNotOrphaned(tangle, hash, targetMilestone)) {
TransactionViewModel tvm = TransactionViewModel.fromHash(tangle, hash);
addTailsToSolidEntryPoints(milestoneIndex, solidEntryPoints, tvm);
solidEntryPoints.put(hash, milestoneIndex);
}

Snapshot initialSnapshot = snapshotProvider.getInitialSnapshot();
initialSnapshot.getSolidEntryPoints().forEach((hash, milestoneIndex) -> {
if (!Hash.NULL_HASH.equals(hash) && targetMilestone.index() - milestoneIndex <= SOLID_ENTRY_POINT_LIFETIME
&& isSolidEntryPoint(tangle, hash, targetMilestone)) {

solidEntryPoints.put(hash, milestoneIndex);
progressLogger.progress();
}

progressLogger.progress();
});

progressLogger.finish();
} catch (Exception e) {
throw new SnapshotException(
"Couldn't process old solid entry point for target milestone " + targetMilestone.index(), e);
} finally {
progressLogger.finish();
}
}

/**
* <p>
* This method retrieves the new solid entry points of the snapshot reference given by the target milestone.
* </p>
* <p>
* A transaction is considered a solid entry point if it is a bundle tail that can be traversed down from a
* non-orphaned transaction that was approved by a milestone that is above the last local snapshot. Or if it is a
* bundle tail of a non-orphaned transaction that was approved by a milestone that is above the last local snapshot.
*
* It iterates over all unprocessed milestones and analyzes their directly and indirectly approved transactions.
* Every transaction is checked for being a solid entry point and added to the passed in map (if it was found to be
* one).
* Every transaction is checked for being not orphaned and the appropriate SEP is added to {@param SolidEntryPoints}
* </p>
*
* @param tangle Tangle object which acts as a database interface
*
*
* @param tangle Tangle object which acts as a database interface
* @param snapshotProvider data provider for the {@link Snapshot}s that are relevant for the node
* @param targetMilestone milestone that is used to generate the solid entry points
* @param targetMilestone milestone that is used to generate the solid entry points
* @param solidEntryPoints map that is used to collect the solid entry points
* @throws SnapshotException if anything goes wrong while determining the solid entry points
* @see #isNotOrphaned(Tangle, Hash, MilestoneViewModel)
*/
private void processNewSolidEntryPoints(Tangle tangle, SnapshotProvider snapshotProvider,
MilestoneViewModel targetMilestone, Map<Hash, Integer> solidEntryPoints) throws SnapshotException {
Expand All @@ -675,8 +688,9 @@ private void processNewSolidEntryPoints(Tangle tangle, SnapshotProvider snapshot
currentMilestone.getHash(),
currentTransaction -> currentTransaction.snapshotIndex() >= currentMilestone.index(),
currentTransaction -> {
if (isSolidEntryPoint(tangle, currentTransaction.getHash(), targetMilestone)) {
solidEntryPoints.put(currentTransaction.getHash(), targetMilestone.index());
if (isNotOrphaned(tangle, currentTransaction.getHash(), targetMilestone)) {
addTailsToSolidEntryPoints(targetMilestone.index(), solidEntryPoints,
currentTransaction);
}
}
);
Expand All @@ -696,4 +710,15 @@ private void processNewSolidEntryPoints(Tangle tangle, SnapshotProvider snapshot
throw new SnapshotException("could not generate the solid entry points for " + targetMilestone, e);
}
}

private void addTailsToSolidEntryPoints(int milestoneIndex, Map<Hash, Integer> solidEntryPoints,
TransactionViewModel currentTransaction) throws TraversalException {
// if tail
if (currentTransaction.getCurrentIndex() == 0) {
solidEntryPoints.put(currentTransaction.getHash(), milestoneIndex);
} else {
Set<? extends Hash> tails = DAGHelper.get(tangle).findTails(currentTransaction);
tails.forEach(tail -> solidEntryPoints.put(tail, milestoneIndex));
}
}
}

0 comments on commit fa79533

Please sign in to comment.