verify-anchor: a certificate is a NON-EMPTY item 6 (AIP-22 stage 5 headers carry an empty certificate slot between anchors)

This commit is contained in:
Aere Network 2026-09-24 00:03:31 +03:00
parent 71412b9792
commit ab90cc5b06

View File

@ -268,7 +268,9 @@ async function carriesCertificate(h) {
if (h < ANCHOR_FROM) return false; if (h < ANCHOR_FROM) return false;
const b = await rpc('eth_getBlockByNumber', ['0x' + h.toString(16), false]); const b = await rpc('eth_getBlockByNumber', ['0x' + h.toString(16), false]);
if (!b || !b.extraData) return false; if (!b || !b.extraData) return false;
try { return rlpRead(hex(b.extraData), 0).item.length >= 6; } catch (e) { return false; } // AIP-22 stage 5: from H_hdr every header has seven elements and the certificate slot (item 6) is an EMPTY list between
// anchors, so a certificate is a NON-EMPTY item 6, never just the count of elements
try { const it = rlpRead(hex(b.extraData), 0).item; return it.length >= 6 && it[5].list && it[5].item.length > 0; } catch (e) { return false; }
} }
let DERIVED_INTERVAL = 0; let DERIVED_INTERVAL = 0;
@ -416,7 +418,7 @@ for (let i = 0; i < COUNT; i++) {
const parent = await rpc('eth_getBlockByNumber', ['0x' + (h - 1).toString(16), false]); const parent = await rpc('eth_getBlockByNumber', ['0x' + (h - 1).toString(16), false]);
const items = rlpRead(hex(b.extraData), 0).item; const items = rlpRead(hex(b.extraData), 0).item;
const vanity = Buffer.from(items[0].item); const vanity = Buffer.from(items[0].item);
if (items.length < 6) { console.log(h + ' FAIL: no certificate element'); bad++; continue; } if (items.length < 6 || !items[5].list || items[5].item.length === 0) { console.log(h + ' FAIL: no certificate element'); bad++; continue; }
const cert = items[5]; const cert = items[5];
const toNested = (node) => (node.list ? node.item.map(toNested) : Buffer.from(node.item)); const toNested = (node) => (node.list ? node.item.map(toNested) : Buffer.from(node.item));
// v1 opens with a LIST ([idx, sig]); v2 opens with the SCALAR 2. Nothing else is accepted. // v1 opens with a LIST ([idx, sig]); v2 opens with the SCALAR 2. Nothing else is accepted.