// 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 };
