Support for Ethereum consensus mechanisms including Ethash Proof-of-Work and Clique Proof-of-Authority.
Functions for working with Clique PoA consensus mechanism, including signer validation and epoch transitions.
/**
* Fixed vanity bytes length in Clique extra data (32 bytes)
*/
const CLIQUE_EXTRA_VANITY: number;
/**
* Fixed seal bytes length in Clique extra data (65 bytes)
*/
const CLIQUE_EXTRA_SEAL: number;
/**
* Returns PoA clique signature hash without seal
* Used for signature verification and signing operations
* @param header - Block header to get signature hash for
* @returns Signature hash as Uint8Array
*/
function cliqueSigHash(header: BlockHeader): Uint8Array;
/**
* Checks if header represents an epoch transition block
* Epoch transitions occur every N blocks and contain signer list updates
* @param header - Block header to check
* @returns True if this is an epoch transition header
*/
function cliqueIsEpochTransition(header: BlockHeader): boolean;
/**
* Returns extra vanity data from Clique header
* Vanity data is the first 32 bytes of extra data field
* @param header - Block header with Clique extra data
* @returns Vanity data as Uint8Array (32 bytes)
*/
function cliqueExtraVanity(header: BlockHeader): Uint8Array;
/**
* Returns extra seal data from Clique header
* Seal data is the last 65 bytes of extra data field containing the signature
* @param header - Block header with Clique extra data
* @returns Seal data as Uint8Array (65 bytes)
*/
function cliqueExtraSeal(header: BlockHeader): Uint8Array;
/**
* Returns the list of signers from an epoch transition header
* Only valid for epoch transition blocks, throws error otherwise
* @param header - Epoch transition block header
* @returns Array of signer addresses
*/
function cliqueEpochTransitionSigners(header: BlockHeader): Address[];
/**
* Returns the signer address from a Clique block header
* Recovers the address from the signature in the seal data
* @param header - Block header with Clique signature
* @returns Address of the block signer
*/
function cliqueSigner(header: BlockHeader): Address;
/**
* Verifies signature against a list of authorized signers
* Checks if the block signer is authorized and signature is valid
* @param header - Block header with Clique signature
* @param signerList - Array of authorized signer addresses
* @returns True if signature is valid and signer is authorized
*/
function cliqueVerifySignature(header: BlockHeader, signerList: Address[]): boolean;Usage Examples:
import {
cliqueSigner,
cliqueVerifySignature,
cliqueIsEpochTransition,
cliqueEpochTransitionSigners,
CLIQUE_EXTRA_VANITY,
CLIQUE_EXTRA_SEAL
} from "@ethereumjs/block";
// Working with a Clique PoA block header
const cliqueHeader = createBlockHeaderFromRPC(cliqueBlockData);
// Get the signer of the block
const signerAddress = cliqueSigner(cliqueHeader);
console.log("Block signed by:", signerAddress.toString());
// Verify the signature against authorized signers
const authorizedSigners = [
Address.fromString("0x1234..."),
Address.fromString("0x5678..."),
Address.fromString("0x9abc..."),
];
const isValidSignature = cliqueVerifySignature(cliqueHeader, authorizedSigners);
console.log("Signature valid:", isValidSignature);
// Check if this is an epoch transition
const isEpochTransition = cliqueIsEpochTransition(cliqueHeader);
console.log("Is epoch transition:", isEpochTransition);
if (isEpochTransition) {
// Get new signer list from epoch transition block
const newSigners = cliqueEpochTransitionSigners(cliqueHeader);
console.log("New signer list:", newSigners.map(addr => addr.toString()));
}
// Examine extra data structure
console.log("Vanity length:", CLIQUE_EXTRA_VANITY); // 32
console.log("Seal length:", CLIQUE_EXTRA_SEAL); // 65
console.log("Total extra data length:", cliqueHeader.extraData.length);Functions for creating sealed Clique blocks with proper signatures.
/**
* Creates a sealed Clique PoA block with signature
* @param blockData - Block data object
* @param cliqueSigner - Signer private key (32 bytes)
* @param opts - Block options
* @returns Sealed Block instance with Clique signature
*/
function createSealedCliqueBlock(
blockData?: BlockData,
cliqueSigner: Uint8Array,
opts?: BlockOptions
): Block;
/**
* Creates a sealed Clique PoA block header with signature
* @param headerData - Header data object
* @param cliqueSigner - Signer private key (32 bytes)
* @param opts - Block options
* @returns Sealed BlockHeader instance with Clique signature
*/
function createSealedCliqueBlockHeader(
headerData?: HeaderData,
cliqueSigner: Uint8Array,
opts?: BlockOptions
): BlockHeader;Usage Examples:
import { createSealedCliqueBlock, createSealedCliqueBlockHeader } from "@ethereumjs/block";
// Private key for signing (32 bytes)
const signerPrivateKey = new Uint8Array([
// ... 32 bytes of private key
]);
// Create sealed Clique block
const sealedBlock = createSealedCliqueBlock({
header: {
number: 100n,
gasLimit: 8000000n,
timestamp: Math.floor(Date.now() / 1000),
extraData: new Uint8Array(32 + 65), // Vanity + seal space
},
transactions: [],
}, signerPrivateKey);
// Create sealed Clique header only
const sealedHeader = createSealedCliqueBlockHeader({
number: 100n,
gasLimit: 8000000n,
timestamp: Math.floor(Date.now() / 1000),
extraData: new Uint8Array(32 + 65), // Vanity + seal space
}, signerPrivateKey);
// Verify the sealed block
const signerAddress = cliqueSigner(sealedBlock.header);
console.log("Block sealed by:", signerAddress.toString());
// The signature should be valid
const isValid = cliqueVerifySignature(sealedBlock.header, [signerAddress]);
console.log("Signature valid:", isValid);Functions for working with Ethash PoW consensus mechanism and difficulty calculations.
/**
* Calculates canonical difficulty for Ethash PoW consensus
* Uses the difficulty adjustment algorithm based on block time and parent difficulty
* Includes difficulty bomb adjustments for specific hard forks
* @param block - Current block
* @param parentBlock - Parent block for difficulty calculation
* @returns Canonical difficulty value for the block
*/
function ethashCanonicalDifficulty(block: Block, parentBlock: Block): bigint;Usage Examples:
import { ethashCanonicalDifficulty, createBlock } from "@ethereumjs/block";
// Create parent block (PoW era)
const parentBlock = createBlock({
header: {
number: 1000000n,
difficulty: 17179869184n, // ~17 billion
timestamp: 1609459200n, // Jan 1, 2021
},
});
// Create child block
const childBlock = createBlock({
header: {
number: 1000001n,
timestamp: 1609459215n, // 15 seconds later (target is ~13-15s)
},
});
// Calculate what the difficulty should be
const canonicalDifficulty = ethashCanonicalDifficulty(childBlock, parentBlock);
console.log("Parent difficulty:", parentBlock.header.difficulty);
console.log("Canonical difficulty:", canonicalDifficulty);
// The difficulty should be similar since block time is close to target
const difficultyChange = canonicalDifficulty - parentBlock.header.difficulty;
console.log("Difficulty change:", difficultyChange);
console.log("Percentage change:", Number(difficultyChange * 100n / parentBlock.header.difficulty));The difficulty adjustment algorithm varies by consensus mechanism and network upgrade.
/**
* Difficulty calculation interface
*/
interface DifficultyCalculation {
/**
* Calculates canonical difficulty using Ethash algorithm
* Factors include:
* - Parent difficulty
* - Block time vs target time
* - Difficulty bomb adjustments
* - Uncle count (pre-Byzantium)
*/
ethashCanonicalDifficulty(block: Block, parentBlock: Block): bigint;
/**
* Header-level difficulty calculation
* Available as method on BlockHeader class
*/
ethashCanonicalDifficulty(parentBlockHeader: BlockHeader): bigint;
}Usage Examples:
import { createBlockHeader } from "@ethereumjs/block";
// Example of difficulty calculation with different block times
const parentHeader = createBlockHeader({
number: 5000000n,
difficulty: 1000000000000000n, // 1 petahash
timestamp: 1609459200n,
});
// Fast block (10 seconds) - difficulty should increase
const fastChildHeader = createBlockHeader({
number: 5000001n,
timestamp: 1609459210n, // 10 seconds later
});
// Slow block (30 seconds) - difficulty should decrease
const slowChildHeader = createBlockHeader({
number: 5000001n,
timestamp: 1609459230n, // 30 seconds later
});
const fastDifficulty = fastChildHeader.ethashCanonicalDifficulty(parentHeader);
const slowDifficulty = slowChildHeader.ethashCanonicalDifficulty(parentHeader);
console.log("Parent difficulty:", parentHeader.difficulty);
console.log("Fast block difficulty:", fastDifficulty);
console.log("Slow block difficulty:", slowDifficulty);
// Fast blocks get higher difficulty, slow blocks get lower difficulty
console.log("Fast block increase:", fastDifficulty > parentHeader.difficulty);
console.log("Slow block decrease:", slowDifficulty < parentHeader.difficulty);Different networks use different consensus mechanisms and require appropriate configuration.
/**
* Network-specific consensus configuration
*/
interface ConsensusConfiguration {
/**
* Ethash PoW networks: mainnet, ropsten (historical)
* Use ethashCanonicalDifficulty for difficulty calculations
*/
ethash: {
networks: string[];
methods: ["ethashCanonicalDifficulty"];
};
/**
* Clique PoA networks: goerli, rinkeby (historical)
* Use clique* functions for signer validation
*/
clique: {
networks: string[];
methods: [
"cliqueSigner",
"cliqueVerifySignature",
"cliqueIsEpochTransition",
"cliqueEpochTransitionSigners"
];
};
/**
* Proof-of-Stake networks: mainnet (post-merge), sepolia
* No consensus-specific functions needed at block level
*/
pos: {
networks: string[];
methods: [];
};
}Usage Examples:
import { Common } from "@ethereumjs/common";
import { createBlock, cliqueSigner } from "@ethereumjs/block";
// Configure for different networks
const mainnetCommon = new Common({ chain: 'mainnet', hardfork: 'london' }); // PoW era
const goerliCommon = new Common({ chain: 'goerli' }); // Clique PoA
const sepoliaCommon = new Common({ chain: 'sepolia' }); // PoS
// Create blocks for different networks
const mainnetBlock = createBlock(blockData, { common: mainnetCommon });
const goerliBlock = createBlock(blockData, { common: goerliCommon });
const sepoliaBlock = createBlock(blockData, { common: sepoliaCommon });
// Use appropriate consensus functions
if (goerliCommon.consensusType() === 'poa') {
const signer = cliqueSigner(goerliBlock.header);
console.log("Goerli block signer:", signer.toString());
}
if (mainnetCommon.consensusType() === 'pow') {
// Would use ethashCanonicalDifficulty for PoW validation
console.log("Mainnet PoW block difficulty:", mainnetBlock.header.difficulty);
}
console.log("Sepolia consensus:", sepoliaCommon.consensusType()); // 'pos'