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

Removes: Solidification thread within the TransactionValidator #1485

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/main/java/com/iota/iri/Iota.java
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,6 @@ public void shutdown() throws Exception {
node.shutdown();
udpReceiver.shutdown();
replicator.shutdown();
transactionValidator.shutdown();
tangle.shutdown();

// free the resources of the snapshot provider last because all other instances need it
Expand Down
110 changes: 0 additions & 110 deletions src/main/java/com/iota/iri/TransactionValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,26 +32,6 @@ public class TransactionValidator {
private static final long MAX_TIMESTAMP_FUTURE = 2L * 60L * 60L;
private static final long MAX_TIMESTAMP_FUTURE_MS = MAX_TIMESTAMP_FUTURE * 1_000L;


/////////////////////////////////fields for solidification thread//////////////////////////////////////

private Thread newSolidThread;

/**
* If true use {@link #newSolidTransactionsOne} while solidifying. Else use {@link #newSolidTransactionsTwo}.
*/
private final AtomicBoolean useFirst = new AtomicBoolean(true);
/**
* Is {@link #newSolidThread} shutting down
*/
private final AtomicBoolean shuttingDown = new AtomicBoolean(false);
/**
* mutex for solidification
*/
private final Object cascadeSync = new Object();
private final Set<Hash> newSolidTransactionsOne = new LinkedHashSet<>();
private final Set<Hash> newSolidTransactionsTwo = new LinkedHashSet<>();

/**
* Constructor for Tangle Validator
*
Expand All @@ -72,21 +52,16 @@ public class TransactionValidator {
* <ol>
* <li>Sets the minimum weight magnitude (MWM). POW on a transaction is validated by counting a certain
* number of consecutive 9s in the end of the transaction hash. The number of 9s is the MWM.</li>
* <li>Starts the transaction solidification thread.</li>
* </ol>
*
*
* @see #spawnSolidTransactionsPropagation()
* @param testnet <tt>true</tt> if we are in testnet mode, this caps {@code mwm} to {@value #TESTNET_MWM_CAP}
* regardless of parameter input.
* @param mwm minimum weight magnitude: the minimal number of 9s that ought to appear at the end of the transaction
* hash
*/
public void init(boolean testnet, int mwm) {
setMwm(testnet, mwm);

newSolidThread = new Thread(spawnSolidTransactionsPropagation(), "Solid TX cascader");
newSolidThread.start();
}

@VisibleForTesting
Expand All @@ -99,16 +74,6 @@ void setMwm(boolean testnet, int mwm) {
}
}

/**
* Shutdown roots to tip solidification thread
* @throws InterruptedException
* @see #spawnSolidTransactionsPropagation()
*/
public void shutdown() throws InterruptedException {
shuttingDown.set(true);
newSolidThread.join();
}

/**
* @return the minimal number of trailing 9s that have to be present at the end of the transaction hash
* in order to validate that sufficient proof of work has been done
Expand Down Expand Up @@ -283,75 +248,6 @@ public boolean checkSolidity(Hash hash, boolean milestone, int maxProcessedTrans
return solid;
}

public void addSolidTransaction(Hash hash) {
synchronized (cascadeSync) {
if (useFirst.get()) {
newSolidTransactionsOne.add(hash);
} else {
newSolidTransactionsTwo.add(hash);
}
}
}

/**
* Creates a runnable that runs {@link #propagateSolidTransactions()} in a loop every {@value #SOLID_SLEEP_TIME} ms
* @return runnable that is not started
*/
private Runnable spawnSolidTransactionsPropagation() {
return () -> {
while(!shuttingDown.get()) {
propagateSolidTransactions();
try {
Thread.sleep(SOLID_SLEEP_TIME);
} catch (InterruptedException e) {
// Ignoring InterruptedException. Do not use Thread.currentThread().interrupt() here.
log.error("Thread was interrupted: ", e);
}
}
};
}

/**
* Iterates over all currently known solid transactions. For each solid transaction, we find
* its children (approvers) and try to quickly solidify them with {@link #quietQuickSetSolid}.
* If we manage to solidify the transactions, we add them to the solidification queue for a traversal by a later run.
*/
@VisibleForTesting
void propagateSolidTransactions() {
Set<Hash> newSolidHashes = new HashSet<>();
useFirst.set(!useFirst.get());
//synchronized to make sure no one is changing the newSolidTransactions collections during addAll
synchronized (cascadeSync) {
//We are using a collection that doesn't get updated by other threads
if (useFirst.get()) {
newSolidHashes.addAll(newSolidTransactionsTwo);
newSolidTransactionsTwo.clear();
} else {
newSolidHashes.addAll(newSolidTransactionsOne);
newSolidTransactionsOne.clear();
}
}
Iterator<Hash> cascadeIterator = newSolidHashes.iterator();
while(cascadeIterator.hasNext() && !shuttingDown.get()) {
try {
Hash hash = cascadeIterator.next();
TransactionViewModel transaction = fromHash(tangle, hash);
Set<Hash> approvers = transaction.getApprovers(tangle).getHashes();
for(Hash h: approvers) {
TransactionViewModel tx = fromHash(tangle, h);
if(quietQuickSetSolid(tx)) {
tx.update(tangle, snapshotProvider.getInitialSnapshot(), "solid|height");
tipsViewModel.setSolid(h);
addSolidTransaction(h);
}
}
} catch (Exception e) {
log.error("Error while propagating solidity upwards", e);
}
}
}


/**
* Updates a transaction after it was stored in the tangle. Tells the node to not request the transaction anymore,
* to update the live tips accordingly, and attempts to quickly solidify the transaction.
Expand Down Expand Up @@ -387,7 +283,6 @@ public void updateStatus(TransactionViewModel transactionViewModel) throws Excep
if(quickSetSolid(transactionViewModel)) {
transactionViewModel.update(tangle, snapshotProvider.getInitialSnapshot(), "solid|height");
tipsViewModel.setSolid(transactionViewModel.getHash());
addSolidTransaction(transactionViewModel.getHash());
}
}

Expand Down Expand Up @@ -449,11 +344,6 @@ private boolean checkApproovee(TransactionViewModel approovee) throws Exception
return approovee.isSolid();
}

@VisibleForTesting
boolean isNewSolidTxSetsEmpty () {
return newSolidTransactionsOne.isEmpty() && newSolidTransactionsTwo.isEmpty();
}

/**
* Thrown if transaction fails {@link #hasInvalidTimestamp} check.
*/
Expand Down
78 changes: 0 additions & 78 deletions src/test/java/com/iota/iri/TransactionValidatorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ public static void tearDown() throws Exception {
public void testMinMwm() throws InterruptedException {
txValidator.init(false, 5);
assertTrue(txValidator.getMinWeightMagnitude() == 13);
txValidator.shutdown();
txValidator.init(false, MAINNET_MWM);
}

Expand Down Expand Up @@ -97,13 +96,6 @@ public void verifyTxIsNotSolid() throws Exception {
assertFalse(txValidator.checkSolidity(tx.getHash(), true));
}

@Test
public void addSolidTransactionWithoutErrors() {
byte[] trits = getTransactionTrits();
Converter.copyTrits(0, trits, 0, trits.length);
txValidator.addSolidTransaction(TransactionHash.calculate(SpongeFactory.Mode.CURLP81, trits));
}

private TransactionViewModel getTxWithBranchAndTrunk() throws Exception {
TransactionViewModel tx, trunkTx, branchTx;
String trytes = "999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999CFDEZBLZQYA9999999999999999999999999999999999999999999ZZWQHWD99C99999999C99999999CKWWDBWSCLMQULCTAAJGXDEMFJXPMGMAQIHDGHRBGEMUYNNCOK9YPHKEEFLFCZUSPMCJHAKLCIBQSGWAS999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999";
Expand All @@ -125,76 +117,6 @@ private TransactionViewModel getTxWithBranchAndTrunk() throws Exception {
return tx;
}

@Test
public void testTransactionPropagation() throws Exception {
TransactionViewModel leftChildLeaf = TransactionTestUtils.createTransactionWithTrytes("CHILDTX");
leftChildLeaf.updateSolid(true);
leftChildLeaf.store(tangle, snapshotProvider.getInitialSnapshot());

TransactionViewModel rightChildLeaf = TransactionTestUtils.createTransactionWithTrytes("CHILDTWOTX");
rightChildLeaf.updateSolid(true);
rightChildLeaf.store(tangle, snapshotProvider.getInitialSnapshot());

TransactionViewModel parent = TransactionTestUtils.createTransactionWithTrunkAndBranch("PARENT",
leftChildLeaf.getHash(), rightChildLeaf.getHash());
parent.updateSolid(false);
parent.store(tangle, snapshotProvider.getInitialSnapshot());

TransactionViewModel parentSibling = TransactionTestUtils.createTransactionWithTrytes("PARENTLEAF");
parentSibling.updateSolid(true);
parentSibling.store(tangle, snapshotProvider.getInitialSnapshot());

TransactionViewModel grandParent = TransactionTestUtils.createTransactionWithTrunkAndBranch("GRANDPARENT", parent.getHash(),
parentSibling.getHash());
grandParent.updateSolid(false);
grandParent.store(tangle, snapshotProvider.getInitialSnapshot());

txValidator.addSolidTransaction(leftChildLeaf.getHash());
while (!txValidator.isNewSolidTxSetsEmpty()) {
txValidator.propagateSolidTransactions();
}

parent = TransactionViewModel.fromHash(tangle, parent.getHash());
assertTrue("Parent tx was expected to be solid", parent.isSolid());
grandParent = TransactionViewModel.fromHash(tangle, grandParent.getHash());
assertTrue("Grandparent was expected to be solid", grandParent.isSolid());
}

@Test
public void testTransactionPropagationFailure() throws Exception {
TransactionViewModel leftChildLeaf = new TransactionViewModel(getTransactionTrits(), getTransactionHash());
leftChildLeaf.updateSolid(true);
leftChildLeaf.store(tangle, snapshotProvider.getInitialSnapshot());

TransactionViewModel rightChildLeaf = new TransactionViewModel(getTransactionTrits(), getTransactionHash());
rightChildLeaf.updateSolid(true);
rightChildLeaf.store(tangle, snapshotProvider.getInitialSnapshot());

TransactionViewModel parent = new TransactionViewModel(getTransactionTritsWithTrunkAndBranch(leftChildLeaf.getHash(),
rightChildLeaf.getHash()), getTransactionHash());
parent.updateSolid(false);
parent.store(tangle, snapshotProvider.getInitialSnapshot());

TransactionViewModel parentSibling = new TransactionViewModel(getTransactionTrits(), getTransactionHash());
parentSibling.updateSolid(false);
parentSibling.store(tangle, snapshotProvider.getInitialSnapshot());

TransactionViewModel grandParent = new TransactionViewModel(getTransactionTritsWithTrunkAndBranch(parent.getHash(),
parentSibling.getHash()), getTransactionHash());
grandParent.updateSolid(false);
grandParent.store(tangle, snapshotProvider.getInitialSnapshot());

txValidator.addSolidTransaction(leftChildLeaf.getHash());
while (!txValidator.isNewSolidTxSetsEmpty()) {
txValidator.propagateSolidTransactions();
}

parent = TransactionViewModel.fromHash(tangle, parent.getHash());
assertTrue("Parent tx was expected to be solid", parent.isSolid());
grandParent = TransactionViewModel.fromHash(tangle, grandParent.getHash());
assertFalse("GrandParent tx was expected to be not solid", grandParent.isSolid());
}

private TransactionViewModel getTxWithoutBranchAndTrunk() throws Exception {
byte[] trits = getTransactionTrits();
TransactionViewModel tx = new TransactionViewModel(trits, TransactionHash.calculate(SpongeFactory.Mode.CURLP81, trits));
Expand Down