-
Notifications
You must be signed in to change notification settings - Fork 370
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rebase with new code and start using locks instead of synchronized
MilestoneViewModel candidateMilestone = MilestoneViewModel.first(tangle); | ||
|
||
while (candidateMilestone != null) { | ||
if (candidateMilestone.index() % 1000 == 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please open an if
block with brackets.
Please also add && log.isDebugEnabled()
and change log level to debug
|
||
while (candidateMilestone != null) { | ||
if (candidateMilestone.index() % 1000 == 0) | ||
log.info("Building snapshot... Consistent: #" + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we are still in Java 8 it is preferable to use StringBuilder
to concatenate strings
@@ -221,20 +223,34 @@ public static boolean isApproved(Snapshot snapshot, Hash hash) { | |||
*/ | |||
private MilestoneViewModel buildSnapshot(Snapshot latestSnapshot) throws Exception { | |||
MilestoneViewModel consistentMilestone = null; | |||
|
|||
synchronized (latestSnapshot.snapshotSyncObject) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use locks. See updated code
@@ -24,7 +24,7 @@ public StateDiffViewModel(final Map<Hash, Long> state, final Hash hash) { | |||
this.stateDiff.state = state; | |||
} | |||
|
|||
public static boolean exists(Tangle tangle, Hash hash) throws Exception { | |||
public static boolean maybeExists(Tangle tangle, Hash hash) throws Exception { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like
Rebased with new code. |
Hey @Desolatora, Git can be annoying sometimes, but we need to get it fixed. |
Checkstyle will fail build
96199e3
to
6662159
Compare
Rebase fixed. |
PR should have one area of responsibility
You don't publish ports if `--net=host` (`--network=host`) is used
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just clicked approved but I see that github claims there are still conflicts..
6662159
to
e078f49
Compare
@GalRogozinski |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks great! - tested it locally in different DB scenarios.
see comment about a failure mode in buildSnapshots()
.
but other than that 👍
consistentMilestone = candidateMilestone; | ||
} | ||
} | ||
candidateMilestone = candidateMilestone.next(tangle); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if a milestone is not consistent (Snapshot.isConsistent == false
), but the next ones are (for example due to DB corruption or malice). then a consistent, but not the actual state would be reached, right?
would be best to fail on an existing, but inconsistent milestone stateDiff
.
snapshotMilestone = snapshotMilestone.nextWithSnapshot(tangle); | ||
MilestoneViewModel candidateMilestone = MilestoneViewModel.first(tangle); | ||
while (candidateMilestone != null) { | ||
if (log.isDebugEnabled() && candidateMilestone.index() % 10000 == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not your fault, but FYI from my tests log.isDebugEnabled()
always returns true in IRI, regardless of the debug
flag.
|
Bug
LedgerValidator initializes wrong consistent milestone after restart when node is not fully synced.
Symptoms
When node is synced to solid milestone X and latest milestone is Y, after restart solid milestone is incorrectly initialized to Z (usually very close to Y).
Cause
Method LedgerValidator.buildSnapshot() is responsible for building the most recent consistent milestone. It uses MilestoneViewModel.firstWithSnapshot() and MilestoneViewModel.nextWithSnapshot() to iterate on every milestone with snapshot then gets the state differences and patches them to the current snapshot. These methods deterministically rely on StateDiffViewModel.exists() which internally uses tangle.maybeHas(). The problem is that tangle.maybeHas() can only guarantee when entry is not present, but does not guarantee if entry is present. This leads to MilestoneViewModel.firstWithSnapshot() and MilestoneViewModel.nextWithSnapshot() sometimes returning milestone without snapshot or more precise milestone without StateDiff. This incorrect behaviour is also supported by the fact that StateDiffViewModel.load() returns an object even if StateDiff is not present. This leads to latestSnapshot being patched with no state differences and incorrect milestone index.
Problems
When node is initialized with wrong solid milestone this may lead to solid milestone tracker appearing frozen while it is trying to solidify next milestone or compute state diff with both operations involving huge number of transactions. Sometimes wrong solid milestone index may lead to "Transaction resolves to incorrect ledger balance" errors (bug: #460).
Proposed fix
Method StateDiffViewModel.isEmpty() is introduced to check if current state difference is empty. LedgerValidator.buildSnapshot() now iterates on every candidate milestone and patches latestSnapshot only with nonempty state differences. This guarantees that initialized consistent milestone is solid.