Skip to content

Commit

Permalink
Better implementation explanation and diagram for getLatestBlock
Browse files Browse the repository at this point in the history
  • Loading branch information
infinisil committed Apr 30, 2021
1 parent 2047680 commit a3b6063
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 11 deletions.
1 change: 1 addition & 0 deletions docs/references/getLatestBlock.drawio
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<mxfile host="app.diagrams.net" modified="2021-04-30T17:02:12.022Z" agent="5.0 (X11)" etag="VlHUmFDAgttu2GtQZtAn" version="14.6.9" type="device"><diagram id="LZnJ9g2oCcXKol6FtnPU" name="Page-1">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</diagram></mxfile>
Binary file added docs/references/getLatestBlock.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 19 additions & 11 deletions docs/references/rpc.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,25 @@ Morpho only interacts with the outside world by making [JSON RPC](https://www.js

Let `interval` be the first parameter. Let `previousHash` be the second parameter.

This call should return the latest checkpoint candidate in the server's proof-of-work chain, constrained by it being a descendant of `previousHash` with a block distance divisible by `interval`. If `previousHash` is `null`, it needs to be a descendant of the genesis block instead. If the constraints can't be met, an empty object should be returned.

This may be implemented as follows:
Let `latest` be the block number of the topmost block in the server's current proof-of-work chain. Then the server should determine the result of this call as follows:
- If `previousHash` is `null`, let `base` be 0.
- If `previousHash` is not `null`:
- Check whether the current chain contains a block with hash `previousHash`. If it does not, return an empty object as the result of the call.
- Otherwise, let `base` be the block number of the block with hash `previousHash`.
- Let `count` be the largest _positive_ integer such that `number = base + count * interval <= latest`.
- If no such integer exists, return an empty object as the result of the call.
- Otherwise, return the `hash` and `number` of the corresponding block.
This call should ensure that the latest checkpoint in the proof-of-work chain matches `previousHash`, and if so, return the latest candidate for the next checkpoint after that. The returned checkpoint candidate has to have a block distance divisible by `interval`. In case this can't be met, return an empty object. This can be implemented as follows:

- If `interval` is less than 2, return an empty object from the RPC call.
Explanation: If we had a checkpoint distance of 1, we would not leave any room for proof-of-work blocks in-between, which would defeat the main motivation for checkpointing: To checkpoint proof-of-work blocks
- Ensure that the hash of the most recently checkpointed proof-of-work block in the proof-of-work chain matches `previousHash`. If it doesn't, return an empty object as the result of the call.
Explanation: This ensures that this node can't issue votes that could fork the proof-of-work chain with conflicting checkpoints, which could happen if this node hasn't received the most recent checkpoint yet.
- Otherwise, let `candidates` be the list of proof-of-work blocks that follow `previousHash` (or the genesis block if `previousHash` is `null`).
Explanation: This also ensures that this node can't issue votes that could fork the proof-of-work chain by signing blocks before the latest checkpoint
- Let `lastIndex'` be `length(candidates) + 1`.
Explanation: This is the last index of the candidate list, but shifted by 2 to include the previously checkpointed block and its checkpoint
- Let `resultIndex` be `lastIndex' - lastIndex' % interval - 2`.
Explanation: This is the latest block with a distance divisible by `interval` to the previously checkpointed block, but shifted back to not include the 2 additional blocks before the candidates.
- If `resultIndex` is negative, return an empty object from the RPC call.
- Otherwise return element at index `resultIndex` of `candidates`

Here is an explanatory diagram for this the index calculations of this implementation for an interval of 3:
![](./getLatestBlock.png)

An implementation of this in Haskell can be found [here](https://github.com/input-output-hk/ECIP-Checkpointing/blob/7f1e4f5b6d16e721d9bcad07fc528f83f97191a4/morpho-checkpoint-node/tests/Test/Morpho/MockRpc.hs#L221-L247).

### Examples

Expand Down

0 comments on commit a3b6063

Please sign in to comment.