Skip to content

Commit

Permalink
Downloadable list of checkpoints (#91)
Browse files Browse the repository at this point in the history
* (feat) Auto-generate checkpoints

* (fix) Fix URL for checkpoints

* (fix) Lint

* (fix) Fix message when there are no checkpoints.

* (feat) Prototestnet and protomainnet checkpoint download tables
  • Loading branch information
rrw-zilliqa authored Feb 11, 2025
1 parent 2cf12e6 commit 666a27f
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 2 deletions.
19 changes: 19 additions & 0 deletions MAGIC.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Magic extra javascript stuff

There is some javascript specified in the mkdocs control file
and stored in `zq2/docs/js` which provides some extra facilities:

## Checkpoints

If you write:

```html
<div
class="zq2_checkpoints"
list="<somewhere_to_get_a_list_from>"
api="API entrypoint"
number=<nr>
/>
```

Then `checkpoints.js` will generate a table inside your div of the last `nr` checkpoints.
96 changes: 96 additions & 0 deletions zq2/docs/js/checkpoints.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
function humanSize(inBytes) {
const NAMES = [ "KiB", "MiB", "GiB", "TiB" ];
let minSize = 1000;
let bestYet = null;
for (let i = 0;i < NAMES.length; ++i) {
let reportAs = inBytes / minSize;
// The replace is horrid - sorry!
bestYet = reportAs.toFixed(2).replace(".00", "") + " " + NAMES[i];
minSize = minSize * 1000;
if (reportAs < 1000) {
return bestYet;
}
}
return reportAs;
}

async function getBlockHash(apiUrl, block) {
const hexBlock = `0x${block.toString(16)}`;
var data = {
id: "1",
jsonrpc: "2.0",
method: "eth_getBlockByNumber",
params: [ hexBlock, false ]
};
return fetch(apiUrl, {
method: "POST",
headers: { "Content-Type": "application/json", },
body: JSON.stringify(data) })
.then((response) => response.json())
.then((data) => {
return data.result.hash
});
}

async function generateTableRow(apiUrl, baseUrl, value) {
// Find the block hash
return getBlockHash(apiUrl, value.block).then(
(h) => {
return `<tr><td><a href="${baseUrl}/${value.key}">${value.block}</a></td><td>${h}</td><td>${humanSize(value.size)}</td></tr>`;
});
}

async function fillCheckpointTableFromElem(elem) {
const listUrl = elem.getAttribute("list");
const apiUrl = elem.getAttribute("api");
const nrCheckpoints = elem.getAttribute("number");
// Get the list of checkpoints.
let inner = fetch(listUrl).then((data) =>
{
parser = new DOMParser();
data.text().then((docText) => {
xmlDoc = parser.parseFromString(docText, "text/xml");
sortedCheckpoints = []
var checkpoints = xmlDoc.getElementsByTagName("Contents");
for (let i = 0;i < checkpoints.length; ++i) {
let c = checkpoints[i];
let key = c.getElementsByTagName("Key")[0].textContent;
let size = c.getElementsByTagName("Size")[0].textContent;
// Now we need the block number.
let block = null;
if (key.startsWith("previous/")) {
block = parseInt(key.substring(10))
} else {
block = parseInt(key)
}
sortedCheckpoints.push({ key, block, size })
}
sortedCheckpoints.sort( (a,b) => b.block - a.block );
const sliced = sortedCheckpoints.slice(0, nrCheckpoints);
if (sliced.length > 0) {
const promises = sliced.map( (v) => generateTableRow(apiUrl, listUrl, v) );
Promise.all(promises).then((values) => {
const tableContents = values.reduce( (acc,v) => acc + v, "")
const tableHeader = "<tr>" +
"<th>Checkpoint</th>" +
"<th>Hash</th>" +
"<th>Size</th>" +
"</tr>";
elem.innerHTML = "<table>" + tableHeader + tableContents + "</table>";
});
} else {
elem.innerHTML = '<p><i>There are no checkpoints currently stored for this network</i></p>';
} })
}
);
}


function fillInCheckpoints() {
var ids = document.getElementsByClassName("zq2_checkpoints");
for (let i =0 ; i < ids.length; ++i) {
fillCheckpointTableFromElem(ids[i])
}
}

document$.subscribe( () => fillInCheckpoints() );
20 changes: 20 additions & 0 deletions zq2/docs/nodes/checkpoints/download.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
id: nodes/checkpoints/download
title: Download checkpoints
---

# Prototestnet checkpoints

<div class="zq2_checkpoints" list="https://checkpoints.zq2-prototestnet.zilliqa.com/" api="https://api.zq2-prototestnet.zilliqa.com" number=4 >
Loading; please wait ..
</div>
<p></p>

# Protomainnet checkpoints

<div class="zq2_checkpoints" list="https://checkpoints.zq2-protomainnet.zilliqa.com/" api="https://api.zq2-protomainnet.zilliqa.com" number=4 >
Loading; please wait ..
</div>



Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ title: Checkpoint

Checkpoints in nodes serve as specific reference points within the blockchain, allowing nodes to synchronize more efficiently when joining or rejoining the network. Instead of processing the entire blockchain from the genesis block, nodes can start from a known, validated state. Below is a detailed guide on how to set up checkpoints.

You can find a list of checkpoints and hashes to download in the menu bar.

## Syncing a Node from a Checkpoint

Before proceeding, ensure you have completed the [Node Setup](../nodes/node.md#setting-up-your-node) section.
Expand Down
4 changes: 3 additions & 1 deletion zq2/mkdocs.in.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ nav:
- Nodes & Validators:
- Overview: nodes/index.md
- Nodes: nodes/node.md
- Checkpoints: nodes/checkpoint.md
- Checkpoints:
- nodes/checkpoints/index.md
- Downloads: nodes/checkpoints/download.md
- Node FAQ: nodes/nodefaq.md
- Validator Monitoring: nodes/validatormonitoring.md
- Tools and SDKs: sdk.md
Expand Down
2 changes: 1 addition & 1 deletion zq2/parent.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ extra_css:

extra_javascript:
- js/versions.js
- js/checkpoints.js
- js/connect.js
- js/chain.js
- js/buffer.js
- js/add-zilliqa-PM-chain.js
- js/add-zilliqa-PT-chain.js


theme:
name: material
logo: assets/zilliqa.svg
Expand Down

0 comments on commit 666a27f

Please sign in to comment.