This page is a placeholder. All examples on this page are currently AI-generated and are not correct. This documentation will be completed in the future with accurate, tested examples.
engine Methods
The engine namespace provides 20 methods for consensus layer integration via the Engine API.
The Engine API is used for communication between execution layer (EL) and consensus layer (CL) clients in post-merge Ethereum. Most application developers won’t interact with these methods directly.
Overview
Access engine methods directly on the provider:
import { Provider } from '@tevm/voltaire/provider';
import { Keccak256 } from '@tevm/voltaire/Keccak256';
// Validate payload (consensus layer → execution layer)
const response = await provider.engine_newPayloadV3(payload);
// Get payload for block production (execution layer → consensus layer)
const payload = await provider.engine_getPayloadV3(payloadId);
Engine API Context
The Engine API implements the communication protocol between:
- Consensus Layer (CL) - Beacon chain, validators, attestations
- Execution Layer (EL) - Transaction execution, state, EVM
Key Concepts:
- Payload - Block execution data (transactions, state root, receipts root)
- Forkchoice - Head, safe, and finalized block hashes
- Payload ID - Identifier for a pending payload being built
Payload Methods
engine_newPayloadV1
Verify and execute a payload (pre-Shapella).
const result = await provider.engine_newPayloadV1(payload);
// Response<PayloadStatus>
engine_newPayloadV2
Verify and execute a payload (Shapella/Shanghai).
const result = await provider.engine_newPayloadV2(payload);
// Response<PayloadStatus>
engine_newPayloadV3
Verify and execute a payload (Cancun - includes blobs).
const result = await provider.engine_newPayloadV3(
payload,
expectedBlobVersionedHashes,
parentBeaconBlockRoot
);
// Response<PayloadStatus>
Parameters:
payload: ExecutionPayload - Block execution data
expectedBlobVersionedHashes: Hash[] - Blob KZG commitments (Cancun)
parentBeaconBlockRoot: Hash - Parent beacon block root (Cancun)
Payload Status:
VALID - Payload executed successfully
INVALID - Payload execution failed
SYNCING - Node is syncing, cannot validate yet
ACCEPTED - Optimistically accepted (pre-finality)
Example:
const result = await provider.engine_newPayloadV3(payload, blobHashes, beaconRoot);
if (!result.error) {
switch (result.result.status) {
case 'VALID':
console.log('Payload valid, hash:', result.result.latestValidHash);
break;
case 'INVALID':
console.error('Invalid payload:', result.result.validationError);
break;
case 'SYNCING':
console.log('Node syncing, try again later');
break;
}
}
Forkchoice Methods
engine_forkchoiceUpdatedV1
Update forkchoice state and optionally start building a new payload (pre-Shapella).
const result = await provider.engine_forkchoiceUpdatedV1(
forkchoiceState,
payloadAttributes
);
// Response<ForkchoiceUpdateResult>
engine_forkchoiceUpdatedV2
Update forkchoice state (Shapella/Shanghai).
const result = await provider.engine_forkchoiceUpdatedV2(
forkchoiceState,
payloadAttributes
);
// Response<ForkchoiceUpdateResult>
engine_forkchoiceUpdatedV3
Update forkchoice state (Cancun).
const result = await provider.engine_forkchoiceUpdatedV3(
forkchoiceState,
payloadAttributes
);
// Response<ForkchoiceUpdateResult>
Parameters:
forkchoiceState: ForkchoiceState - Head, safe, and finalized hashes
payloadAttributes?: PayloadAttributes - Optional payload building parameters
Forkchoice State:
interface ForkchoiceState {
headBlockHash: Hash; // Current head
safeBlockHash: Hash; // Safe (justified) block
finalizedBlockHash: Hash; // Finalized block
}
Example:
import { Keccak256 } from '@tevm/voltaire/Keccak256';
const forkchoiceState = {
headBlockHash: Hash('0xabc...'),
safeBlockHash: Hash('0xdef...'),
finalizedBlockHash: Hash('0x123...')
};
// Update forkchoice
const result = await provider.engine_forkchoiceUpdatedV3(forkchoiceState);
if (!result.error && result.result.payloadStatus.status === 'VALID') {
console.log('Forkchoice updated successfully');
}
// Update forkchoice and start building payload
const buildResult = await provider.engine_forkchoiceUpdatedV3(
forkchoiceState,
{
timestamp: Quantity(Date.now() / 1000),
prevRandao: Hash('0x...'),
suggestedFeeRecipient: Address('0x...')
}
);
if (!buildResult.error && buildResult.result.payloadId) {
console.log('Started building payload:', buildResult.result.payloadId);
}
Payload Building Methods
engine_getPayloadV1
Retrieve a built payload by ID (pre-Shapella).
const payload = await provider.engine_getPayloadV1(payloadId);
// Response<ExecutionPayload>
engine_getPayloadV2
Retrieve a built payload by ID (Shapella/Shanghai).
const payload = await provider.engine_getPayloadV2(payloadId);
// Response<ExecutionPayloadWithValue>
engine_getPayloadV3
Retrieve a built payload by ID (Cancun - includes blobs).
const payload = await provider.engine_getPayloadV3(payloadId);
// Response<ExecutionPayloadWithBlobs>
Parameters:
payloadId: Hex - Payload identifier from forkchoiceUpdated
Example:
// Start building payload
const forkchoiceResult = await provider.engine_forkchoiceUpdatedV3(
forkchoiceState,
payloadAttributes
);
if (!forkchoiceResult.error && forkchoiceResult.result.payloadId) {
const payloadId = forkchoiceResult.result.payloadId;
// Wait for payload to build (typically 0-12 seconds)
await new Promise(resolve => setTimeout(resolve, 1000));
// Retrieve built payload
const payloadResult = await provider.engine_getPayloadV3(payloadId);
if (!payloadResult.error) {
console.log('Payload:', payloadResult.result.executionPayload);
console.log('Block value:', payloadResult.result.blockValue);
console.log('Blobs:', payloadResult.result.blobsBundle);
}
}
Blob Methods
engine_getBlobsV1
Retrieve blob sidecars for a list of blob versioned hashes.
const blobs = await provider.engine_getBlobsV1(blobVersionedHashes);
// Response<BlobAndProof[]>
Parameters:
blobVersionedHashes: Hash[] - KZG commitment hashes
Example:
import { Keccak256 } from '@tevm/voltaire/Keccak256';
// Get blobs for specific commitments
const blobHashes = [
Hash('0x01abc...'), // Blob versioned hash (sha256(kzg_commitment)[0] = 0x01)
Hash('0x01def...')
];
const blobsResult = await provider.engine_getBlobsV1(blobHashes);
if (!blobsResult.error) {
blobsResult.result.forEach((blobData, i) => {
console.log(`Blob ${i}:`);
console.log(' Data:', blobData.blob);
console.log(' Commitment:', blobData.commitment);
console.log(' Proof:', blobData.proof);
});
}
Exchange Capabilities
engine_exchangeCapabilities
Exchange supported Engine API capabilities between CL and EL.
const capabilities = await provider.engine_exchangeCapabilities([
'engine_newPayloadV3',
'engine_forkchoiceUpdatedV3',
'engine_getPayloadV3'
]);
// Response<string[]>
Example:
// Declare CL capabilities
const clCapabilities = [
'engine_newPayloadV3',
'engine_forkchoiceUpdatedV3',
'engine_getPayloadV3',
'engine_getBlobsV1'
];
const result = await provider.engine_exchangeCapabilities(clCapabilities);
if (!result.error) {
console.log('EL supports:', result.result);
// Check for specific capability
const supportsCancun = result.result.includes('engine_newPayloadV3');
console.log('Cancun support:', supportsCancun);
}
Transition Methods
engine_exchangeTransitionConfigurationV1
Exchange transition configuration (for merge preparation).
const config = await provider.engine_exchangeTransitionConfigurationV1({
terminalTotalDifficulty: Quantity(58750000000000000000000n),
terminalBlockHash: Hash('0x0000000000000000000000000000000000000000000000000000000000000000'),
terminalBlockNumber: Quantity(0)
});
// Response<TransitionConfiguration>
Note: This method was used during the merge transition and is rarely needed in post-merge operations.
Block Validation Methods
engine_getPayloadBodiesByHashV1
Get block bodies (transactions only) by block hashes.
const bodies = await provider.engine_getPayloadBodiesByHashV1([
Hash('0xabc...'),
Hash('0xdef...')
]);
// Response<ExecutionPayloadBody[]>
engine_getPayloadBodiesByRangeV1
Get block bodies for a range of block numbers.
const bodies = await provider.engine_getPayloadBodiesByRangeV1(
Quantity(1000000), // Start block
Quantity(100) // Count
);
// Response<ExecutionPayloadBody[]>
Example:
// Get last 10 block bodies
const latestBlock = await provider.eth_blockNumber();
if (!latestBlock.error) {
const start = latestBlock.result - 10n;
const bodies = await provider.engine_getPayloadBodiesByRangeV1(
Quantity(start),
Quantity(10)
);
if (!bodies.error) {
bodies.result.forEach((body, i) => {
console.log(`Block ${start + BigInt(i)}:`, body.transactions.length, 'txs');
});
}
}
Usage Patterns
Block Production Flow
// 1. CL notifies EL of new forkchoice and requests payload
const forkchoiceResult = await provider.engine_forkchoiceUpdatedV3(
{
headBlockHash: newHead,
safeBlockHash: safeBlock,
finalizedBlockHash: finalizedBlock
},
{
timestamp: Quantity(nextSlotTime),
prevRandao: randomness,
suggestedFeeRecipient: validatorFeeRecipient,
withdrawals: withdrawalsList
}
);
// 2. EL returns payload ID
const payloadId = forkchoiceResult.result.payloadId;
// 3. CL waits for payload to build
await sleep(4000); // 4 second block time
// 4. CL retrieves built payload
const payloadResult = await provider.engine_getPayloadV3(payloadId);
const payload = payloadResult.result.executionPayload;
// 5. CL proposes block to beacon chain
// ... beacon chain operations ...
// 6. When block is attested, CL notifies EL to import
const validationResult = await provider.engine_newPayloadV3(
payload,
blobVersionedHashes,
parentBeaconBlockRoot
);
// 7. CL updates forkchoice to make new block head
await provider.engine_forkchoiceUpdatedV3({
headBlockHash: payload.blockHash,
safeBlockHash: safeBlock,
finalizedBlockHash: finalizedBlock
});
Version Compatibility
| Method Version | Fork | Key Features |
|---|
| V1 | Bellatrix (Merge) | Basic Engine API |
| V2 | Shapella (Shanghai) | Withdrawals support |
| V3 | Cancun (Dencun) | Blob transactions (EIP-4844) |
Always use the latest version compatible with your target fork.
Error Handling
Engine API methods return detailed error information:
const result = await provider.engine_newPayloadV3(payload, blobHashes, beaconRoot);
if (result.error) {
console.error('RPC error:', result.error.code, result.error.message);
} else if (result.result.status === 'INVALID') {
console.error('Validation error:', result.result.validationError);
console.error('Latest valid hash:', result.result.latestValidHash);
}
Type Reference
All parameter and return types are defined in the JSON-RPC types module.
Next Steps
Resources