Conversation
The length of the core is computed via the span of the merkle roots but is also loaded via the header's tree length.
Picks the rightSpan as the index to get an upgrade for to target the index.
This allows the generated proof to target a merkle tree node even if it's a sub-root of the current roots.
If the requesting core receives a data message with the upgrade proof and when checking for a conflict errors when checking the local proof, then attempt to apply the upgrade nodes from the remote locally and recheck. This allows cores to automatically repair when detecting a conflict in cases where the tree nodes are missing.
In case this function is used elsewhere in the future.
This prevents tree nodes from being modified during other merkle tree modification. Also ensures that the checks and modifications are atomic so that at the time of repair the tree used to verify the proof will be the tree modified.
Helpful for logging the failure case when a proof is out of date. Is the inverse of the `repaired` event. Finally helps deflake the tests for merkle tree recovery which can fail when just waiting on `repairing` event as the tree nodes expected to be applied (because the proof passed by a peer was valid) are not applied yet when checking the tree node to be applied.
This makes it clearer that the check for the node is after either success or failure. Especially helpful for showing that the test fails if you remove the state mutex locks in `_repairTreeNodes()`.
This mode makes the test for truncating race condition moot as it will throw when trying to truncate now. Appends are also protected.
|
In addition to manual fully remote proofs, merkle tree roots can be repaired automatically when a core is opened with missing root nodes and Repair ModeA core opened with no roots but a header tree length and The repair lifecycle can be tracked via the following added events:
Test cases for showcasing repairing via remote peer and preventing appending and truncating while in repair mode were added. |
Disabled by setting `pushOnly` mode.
Also do not send `sync` message as a repairing core is not a valid source for an upgrade. Set pushOnly mode as soon as repair mode is enabled.
Guards prevent requests from peers sending messages that could change the merkle tree mid update. Core will also require reopening to disable the repair mode.
lib/merkle-tree.js
Outdated
| if (tx === undefined) throw INVALID_OPERATION('No database batch was passed') | ||
|
|
||
| if (this.session.core._repairMode) { | ||
| throw Error('Cannot commit while repair mode is on') |
There was a problem hiding this comment.
be nice to use a typed error from hypercore-errors
There was a problem hiding this comment.
Used ASSERTION and changed the assert() in lib/session-state.js to use the same for the same error. These will ensure its thrown as uncaughts by safety-catch.
This allows the hypercore to automatically repair itself when it enters repair mode.
Was using the merkle index so was outputting the wrong hash.
First step is to allow missing roots when
readying a hypercore. The roots were used to determine the length based on their span. If the roots are not available the header's treelengthvalue is used.The general technique to recover a merkle tree node, is to pass a fully remote proof from a peer with the node to the affected peer.
Since proofs include the nodes as part of the proof, the peer without the node can directly write the nodes after verifying them. A new
upgradeargument was added tofully-remote-proof.js'sproof()to support overriding the defaultupgradefor the sender'slength. This allows the proof generated for recovery to target subtree roots.Tests were added to demonstrate this flow for both root nodes and subtree root nodes. A new assertion was added for the
fully-remote-proof.jstests as well for the addedupgradeargument.