// Shared RLP block-header encoder used by the anchor tests. // // Adaptive standard-Ethereum header encoder: it appends the London / Shanghai / // Cancun / Prague trailing fields only when the block object carries them, which // mirrors how a node serializes its header. This lets one function reconstruct // - AERE's genesis block (Shanghai layout, 17 fields), which it matches exactly, and // - the local hardhat block under either the "shanghai" or "cancun" hardfork. // // QBFT note: AERE is a Hyperledger Besu QBFT chain. For the canonical block // hash of a NON-genesis block, Besu strips the commit seals out of extraData // before hashing, and the exact post-Cancun serialization was not reproducible // from eth_getBlockByNumber alone (see the deploy script's header sourcing). // The anchor CONTRACT is agnostic to all of this: it only checks // keccak256(header) == blockhash and reads stateRoot at a fixed offset. const { ethers } = require("ethers"); // RLP-encode an integer quantity with minimal big-endian bytes (0 -> "0x"). function q(hexOrNum) { let v = BigInt(hexOrNum); if (v === 0n) return "0x"; let s = v.toString(16); if (s.length % 2) s = "0" + s; return "0x" + s; } // Build the RLP header bytes for a standard-Ethereum header object `b` // (fields are 0x-hex strings as returned by eth_getBlockByNumber). function encodeHeader(b) { const fields = [ b.parentHash, b.sha3Uncles, b.miner, b.stateRoot, b.transactionsRoot, b.receiptsRoot, b.logsBloom, q(b.difficulty), q(b.number), q(b.gasLimit), q(b.gasUsed), q(b.timestamp), b.extraData && b.extraData !== "0x" ? b.extraData : "0x", b.mixHash, b.nonce, ]; if (b.baseFeePerGas != null) fields.push(q(b.baseFeePerGas)); // London if (b.withdrawalsRoot != null) fields.push(b.withdrawalsRoot); // Shanghai if (b.blobGasUsed != null) fields.push(q(b.blobGasUsed)); // Cancun if (b.excessBlobGas != null) fields.push(q(b.excessBlobGas)); // Cancun if (b.parentBeaconBlockRoot != null) fields.push(b.parentBeaconBlockRoot); // Cancun if (b.requestsHash != null) fields.push(b.requestsHash); // Prague return ethers.encodeRlp(fields); } module.exports = { q, encodeHeader };