Skip to content
Merged
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
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ CHAINALYSIS_KEY=
## badge at a branch/fork while the PET PR is in review.
# NEXT_PUBLIC_PET_REFERENCE_URL=https://raw.githubusercontent.com/open-web3-stack/polkadot-ecosystem-tests/master/packages/shared/src/snowbridge/referencePreimages.json
# NEXT_PUBLIC_PET_REFERENCE_BLOB_URL=https://github.com/open-web3-stack/polkadot-ecosystem-tests/blob/master/packages/shared/src/snowbridge/referencePreimages.json

## Governance badge: GitHub API URL used to show "last verified against live chains"
## (last commit to PET's known-good block file, updated by its 6-hourly cron).
# NEXT_PUBLIC_PET_KNOWN_GOOD_URL=https://api.github.com/repos/open-web3-stack/polkadot-ecosystem-tests/commits?path=KNOWN_GOOD_BLOCK_NUMBERS_POLKADOT.env&per_page=1
22 changes: 21 additions & 1 deletion __tests__/preimageReference.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { compareToReference } from "@/lib/preimageReference";
import { compareToReference, parseLastVerified } from "@/lib/preimageReference";
import type { ReferenceFile } from "@/lib/preimageReference";
import { describe, expect, test } from "vitest";

Expand Down Expand Up @@ -68,3 +68,23 @@ describe("compareToReference", () => {
).toBe("mismatch");
});
});

describe("parseLastVerified", () => {
test("extracts the committer date of the first commit", () => {
const d = parseLastVerified([
{ commit: { committer: { date: "2026-07-07T12:00:00Z" } } },
]);
expect(d?.toISOString()).toBe("2026-07-07T12:00:00.000Z");
});

test("returns null for an empty array", () => {
expect(parseLastVerified([])).toBeNull();
});

test("returns null for a malformed / missing date", () => {
expect(parseLastVerified([{ commit: { committer: {} } }])).toBeNull();
expect(
parseLastVerified([{ commit: { committer: { date: "not-a-date" } } }]),
).toBeNull();
});
});
18 changes: 11 additions & 7 deletions components/governance/HaltBridgeForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,15 @@ function PreimageResult({
);
}

// Relative age of the last live-chain verification, e.g. "3 hours ago".
function formatVerifiedAgo(date: Date): string {
const hours = Math.round((Date.now() - date.getTime()) / 3_600_000);
if (hours < 1) return "less than an hour ago";
if (hours < 24) return `${hours} hour${hours === 1 ? "" : "s"} ago`;
const days = Math.round(hours / 24);
return `${days} day${days === 1 ? "" : "s"} ago`;
}

function ReferenceCheck({
operation,
result,
Expand Down Expand Up @@ -842,8 +851,6 @@ function ReferenceCheck({
}

if (verdict.kind === "match") {
const bh = verdict.reference.bridgeHubRuntime;
const ah = verdict.reference.assetHubRuntime;
return (
<div className="rounded-2xl p-4 space-y-2 bg-green-500/10 border border-green-500/40">
<div className="flex items-center gap-2 text-sm font-semibold text-green-700">
Expand All @@ -854,11 +861,8 @@ function ReferenceCheck({
These bytes are byte-identical to the canonical full {operation}{" "}
pinned in polkadot-ecosystem-tests and re-executed against forked live
chains on a schedule.
{ah && bh
? ` Reference generated against Asset Hub ${ah.specVersion} / Bridge Hub ${bh.specVersion}` +
(verdict.reference.generatedAt
? ` (${verdict.reference.generatedAt}).`
: ".")
{verdict.lastVerifiedAt
? ` Last verified against live chains ${formatVerifiedAgo(verdict.lastVerifiedAt)}.`
: ""}
</p>
{disclaimer}
Expand Down
59 changes: 53 additions & 6 deletions lib/preimageReference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@ export const PET_REFERENCE_BLOB_URL =
process.env.NEXT_PUBLIC_PET_REFERENCE_BLOB_URL ??
"https://github.com/open-web3-stack/polkadot-ecosystem-tests/blob/master/packages/shared/src/snowbridge/referencePreimages.json";

// GitHub API: latest commit that touched PET's known-good block file. That file
// is committed by the 6-hourly `update-known-good` cron only when the whole
// Polkadot suite (our halt/resume test included) passes against fresh live
// blocks, so its commit date is a live "last verified against live chains"
// signal. Derived from CI rather than baked into the reference, so it's always
// current and never goes stale. (Proxy note: it reflects the whole Polkadot
// suite passing, not our test alone; if any Polkadot test fails the date simply
// stops advancing, which is itself a useful staleness signal.)
export const PET_KNOWN_GOOD_COMMITS_URL =
process.env.NEXT_PUBLIC_PET_KNOWN_GOOD_URL ??
"https://api.github.com/repos/open-web3-stack/polkadot-ecosystem-tests/commits?path=KNOWN_GOOD_BLOCK_NUMBERS_POLKADOT.env&per_page=1";

export type Operation = "halt" | "resume";

export interface ReferencePreimageEntry {
Expand All @@ -35,9 +47,6 @@ export interface ReferencePreimageEntry {

export interface ReferenceFile {
description?: string;
generatedAt?: string;
assetHubRuntime?: { specName: string; specVersion: number };
bridgeHubRuntime?: { specName: string; specVersion: number };
halt: ReferencePreimageEntry;
resume: ReferencePreimageEntry;
}
Expand All @@ -60,7 +69,7 @@ export async function sdkProducesDeterministicPreimage(): Promise<boolean> {
}

export type ReferenceVerdict =
| { kind: "match"; reference: ReferenceFile }
| { kind: "match"; reference: ReferenceFile; lastVerifiedAt: Date | null }
| {
kind: "mismatch";
reference: ReferenceFile;
Expand Down Expand Up @@ -98,6 +107,38 @@ export async function fetchReference(
return (await res.json()) as ReferenceFile;
}

/**
* Pure extractor for the last-verified date from the GitHub commits API
* response. Exposed for unit testing. Returns null for an empty/malformed
* response or an unparseable date.
*/
export function parseLastVerified(
commits: Array<{ commit?: { committer?: { date?: string } } }>,
): Date | null {
const iso = commits?.[0]?.commit?.committer?.date;
if (!iso) return null;
const date = new Date(iso);
return Number.isNaN(date.getTime()) ? null : date;
}

// Fetch the "last verified against live chains" timestamp. Never throws: any
// failure (network, rate limit, shape change) resolves to null so the badge
// simply omits the line rather than breaking the whole check.
export async function fetchLastVerifiedAt(
signal?: AbortSignal,
): Promise<Date | null> {
try {
const res = await fetch(PET_KNOWN_GOOD_COMMITS_URL, {
signal,
headers: { Accept: "application/vnd.github+json" },
});
if (!res.ok) return null;
return parseLastVerified(await res.json());
} catch {
return null;
}
}

export async function verifyAgainstReference(
operation: Operation,
result: { hash: string; callData: string },
Expand All @@ -107,8 +148,14 @@ export async function verifyAgainstReference(
return { kind: "unsupported" };
}
let reference: ReferenceFile;
let lastVerifiedAt: Date | null = null;
try {
reference = await fetchReference(signal);
// fetchLastVerifiedAt never throws, so this only rejects if the reference
// fetch itself fails.
[reference, lastVerifiedAt] = await Promise.all([
fetchReference(signal),
fetchLastVerifiedAt(signal),
]);
} catch (e) {
return {
kind: "unavailable",
Expand All @@ -117,7 +164,7 @@ export async function verifyAgainstReference(
}
const verdict = compareToReference(operation, result, reference);
if (verdict === "match") {
return { kind: "match", reference };
return { kind: "match", reference, lastVerifiedAt };
}
const expected = operation === "halt" ? reference.halt : reference.resume;
return { kind: "mismatch", reference, expected };
Expand Down
Loading