Skip to content

Commit

Permalink
Implement pectra devnet-5 spec (#3807)
Browse files Browse the repository at this point in the history
* evm: add devnet-5 EIP-7702 changes

* vm: add devnet-5 EIP-7685 changes

* monorepo: make cspell happy

* vm/client: fix tests

* evm: remove redundant test

* remove accidental console.log

* remove 7742 and add 7691 independently

* fix t8ntool empty requests reporting

* client: fix engine reporting empty requests

* t8n: fix requests reporting

* Implement EIP 7623: calldata cost increase (#3813)

* common/evm/vm: implement EIP7623 calldata cost increase

* move the floorcost update and add debug log

* fix t8ntool empty requests reporting

* common: add 7623

* tx: add 7623 validator

* t8n: throw on invalid txs

* make cspell happy

---------

Co-authored-by: harkamal <gajinder@g11.in>

* client: fix requests contract address (devnet-5) (#3818)

* update chainid to uint256

* evm: update bls gas (eips PR 9097)

* evm: bls update msm gas (eips PR 9116)

* evm: bls update pairing gas (eips PR 9098)

* evm: rename bls files and remove g1mul, g2mul (eips PR 8945)

* evm: update 2537 addresses in test

* tx: add eip-7691 param

* tx: add required params to common

* vm/tests: update 7002 test: correctly deploy withdrawal contract

* client: update genesis contracts

* evm: update bls test files

* vm: 2935 update history serve window

* evm: EXTCODE* do not follow 7702 delegations for gas calculations

* vm: t8n fix: exit early on non-existent 2935 code

* vm: move floor check after applying refund

* evm: update bls cases

* evm/common: cleanup pr

* monorepo: casing maxblob -> maxBlob

* tx: tx tests support prague

* tx: add missing forks

* client: switch cl request types

---------

Co-authored-by: harkamal <gajinder@g11.in>
Co-authored-by: Lucas Saldanha <lucascrsaldanha@gmail.com>
  • Loading branch information
3 people authored Jan 13, 2025
1 parent 15994b9 commit 99cfdd6
Show file tree
Hide file tree
Showing 51 changed files with 797 additions and 490 deletions.
4 changes: 2 additions & 2 deletions packages/block/src/block/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ export class Block {
}
}
if (this.common.isActivatedEIP(4844)) {
const blobGasLimit = this.common.param('maxblobGasPerBlock')
const blobGasLimit = this.common.param('maxBlobGasPerBlock')
const blobGasPerBlob = this.common.param('blobGasPerBlob')
if (tx instanceof Blob4844Tx) {
blobGasUsed += BigInt(tx.numBlobs()) * blobGasPerBlob
Expand Down Expand Up @@ -354,7 +354,7 @@ export class Block {
*/
validateBlobTransactions(parentHeader: BlockHeader) {
if (this.common.isActivatedEIP(4844)) {
const blobGasLimit = this.common.param('maxblobGasPerBlock')
const blobGasLimit = this.common.param('maxBlobGasPerBlock')
const blobGasPerBlob = this.common.param('blobGasPerBlob')
let blobGasUsed = BIGINT_0

Expand Down
5 changes: 4 additions & 1 deletion packages/block/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,10 @@ export function genRequestsRoot(

let flatRequests = new Uint8Array()
for (const req of requests) {
flatRequests = concatBytes(flatRequests, sha256Function(req.bytes))
if (req.bytes.length > 1) {
// Only append requests if they have content
flatRequests = concatBytes(flatRequests, sha256Function(req.bytes))
}
}

return sha256Function(flatRequests)
Expand Down
13 changes: 11 additions & 2 deletions packages/block/src/params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const paramsBlock: ParamsDict = {
gasLimitBoundDivisor: 1024, // The bound divisor of the gas limit, used in update calculations
targetBlobGasPerBlock: 0, // Base value needed here since called pre-4844 in BlockHeader.calcNextExcessBlobGas()
blobGasPerBlob: 0,
maxblobGasPerBlock: 0,
maxBlobGasPerBlock: 0,
// format
maxExtraDataSize: 32, // Maximum size extra data may be after Genesis
// pow
Expand Down Expand Up @@ -72,7 +72,7 @@ export const paramsBlock: ParamsDict = {
// gasConfig
targetBlobGasPerBlock: 393216, // The target blob gas consumed per block
blobGasPerBlob: 131072, // The base fee for blob gas per blob
maxblobGasPerBlock: 786432, // The max blob gas allowable per block
maxBlobGasPerBlock: 786432, // The max blob gas allowable per block
blobGasPriceUpdateFraction: 3338477, // The denominator used in the exponential when calculating a blob gas price
// gasPrices
simplePerBlobGas: 12000, // The basic gas fee for each blob
Expand All @@ -85,4 +85,13 @@ export const paramsBlock: ParamsDict = {
// pow
difficultyBombDelay: 11400000, // the amount of blocks to delay the difficulty bomb with
},
/**
. * Blob throughput increase
. */
7691: {
// gasConfig
targetBlobGasPerBlock: 786432, // The target blob gas consumed per block
maxBlobGasPerBlock: 1179648, // The max blob gas allowable per block
blobGasPriceUpdateFraction: 5007716, // The denominator used in the exponential when calculating a blob gas price
},
}
4 changes: 2 additions & 2 deletions packages/client/src/miner/pendingBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ export class PendingBlock {
// Get if and how many blobs are allowed in the tx
let allowedBlobs
if (vm.common.isActivatedEIP(4844)) {
const blobGasLimit = vm.common.param('maxblobGasPerBlock')
const blobGasLimit = vm.common.param('maxBlobGasPerBlock')
const blobGasPerBlob = vm.common.param('blobGasPerBlob')
allowedBlobs = Number(blobGasLimit / blobGasPerBlob)
} else {
Expand Down Expand Up @@ -270,7 +270,7 @@ export class PendingBlock {
let allowedBlobs
if (vm.common.isActivatedEIP(4844)) {
const bundle = this.blobsBundles.get(payloadId) ?? { blobs: [], commitments: [], proofs: [] }
const blobGasLimit = vm.common.param('maxblobGasPerBlock')
const blobGasLimit = vm.common.param('maxBlobGasPerBlock')
const blobGasPerBlob = vm.common.param('blobGasPerBlob')
allowedBlobs = Number(blobGasLimit / blobGasPerBlob) - bundle.blobs.length
} else {
Expand Down
13 changes: 12 additions & 1 deletion packages/client/src/rpc/modules/engine/util/getPayload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,20 @@ export const blockToExecutionPayload = (
// ethereumjs does not provide any transaction censoring detection (yet) to suggest
// overriding builder/mev-boost blocks
const shouldOverrideBuilder = false

let executionRequests = undefined
if (requests !== undefined) {
executionRequests = []
for (const request of requests) {
if (request.bytes.length > 1) {
executionRequests.push(bytesToHex(request.bytes))
}
}
}

return {
executionPayload,
executionRequests: requests?.map((req) => bytesToHex(req.data)),
executionRequests,
blockValue: bigIntToHex(value),
blobsBundle,
shouldOverrideBuilder,
Expand Down
49 changes: 27 additions & 22 deletions packages/client/src/rpc/modules/engine/util/newPayload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,30 +57,35 @@ export const validateAndGen7685RequestsHash = (
common: Common,
executionRequests: PrefixedHexString[],
): PrefixedHexString => {
let validationError: string | null = null

const requests: CLRequest<CLRequestType>[] = []
let requestIndex = 0
if (common.isActivatedEIP(6110)) {
requests.push(new CLRequest(CLRequestType.Deposit, hexToBytes(executionRequests[requestIndex])))
requestIndex++
}
if (common.isActivatedEIP(7002)) {
requests.push(
new CLRequest(CLRequestType.Withdrawal, hexToBytes(executionRequests[requestIndex])),
)
requestIndex++
}
if (common.isActivatedEIP(7251)) {
requests.push(
new CLRequest(CLRequestType.Consolidation, hexToBytes(executionRequests[requestIndex])),
)
requestIndex++
}

if (requestIndex !== executionRequests.length) {
validationError = `Invalid executionRequests=${executionRequests.length} expected=${requestIndex}`
throw validationError
for (const request of executionRequests) {
const bytes = hexToBytes(request)
if (bytes.length === 0) {
throw new Error('Got a request without a request-identifier')
}
switch (bytes[0]) {
case CLRequestType.Deposit:
if (!common.isActivatedEIP(6110)) {
throw new Error(`Deposit requests are not active`)
}
requests.push(new CLRequest(CLRequestType.Deposit, bytes.slice(1)))
break
case CLRequestType.Withdrawal:
if (!common.isActivatedEIP(7002)) {
throw new Error(`Withdrawal requests are not active`)
}
requests.push(new CLRequest(CLRequestType.Withdrawal, bytes.slice(1)))
break
case CLRequestType.Consolidation:
if (!common.isActivatedEIP(7251)) {
throw new Error(`Consolidation requests are not active`)
}
requests.push(new CLRequest(CLRequestType.Consolidation, bytes.slice(1)))
break
default:
throw new Error(`Unknown request identifier: got ${bytes[0]}`)
}
}

const sha256Function = common.customCrypto.sha256 ?? sha256
Expand Down
4 changes: 2 additions & 2 deletions packages/client/src/rpc/modules/eth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1160,7 +1160,7 @@ export class Eth {
// Blob Transactions sent over RPC are expected to be in Network Wrapper format
tx = createBlob4844TxFromSerializedNetworkWrapper(txBuf, { common })

const blobGasLimit = tx.common.param('maxblobGasPerBlock')
const blobGasLimit = tx.common.param('maxBlobGasPerBlock')
const blobGasPerBlob = tx.common.param('blobGasPerBlob')

if (BigInt((tx.blobs ?? []).length) * blobGasPerBlob > blobGasLimit) {
Expand Down Expand Up @@ -1402,7 +1402,7 @@ export class Eth {
let blobGasUsedRatio = 0
if (b.header.excessBlobGas !== undefined) {
baseFeePerBlobGas = b.header.getBlobGasPrice()
const max = b.common.param('maxblobGasPerBlock')
const max = b.common.param('maxBlobGasPerBlock')
blobGasUsedRatio = Number(blobGasUsed) / Number(max)
}

Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/service/txpool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ export class TxPool {
}

pruneBlobsAndProofsCache() {
const blobGasLimit = this.config.chainCommon.param('maxblobGasPerBlock')
const blobGasLimit = this.config.chainCommon.param('maxBlobGasPerBlock')
const blobGasPerBlob = this.config.chainCommon.param('blobGasPerBlob')
const allowedBlobsPerBlock = Number(blobGasLimit / blobGasPerBlob)

Expand Down
2 changes: 1 addition & 1 deletion packages/client/test/miner/pendingBlock.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ describe('[PendingBlock]', async () => {
const fillProofs = blobsToProofs(kzg, fillBlobs, fillCommitments)
const fillBlobAndProof = { blob: fillBlobs[0], proof: fillProofs[0] }

const blobGasLimit = txPool['config'].chainCommon.param('maxblobGasPerBlock')
const blobGasLimit = txPool['config'].chainCommon.param('maxBlobGasPerBlock')
const blobGasPerBlob = txPool['config'].chainCommon.param('blobGasPerBlob')
const allowedBlobsPerBlock = Number(blobGasLimit / blobGasPerBlob)
const allowedLength = allowedBlobsPerBlock * txPool['config'].blobsAndProofsCacheBlocks
Expand Down
55 changes: 32 additions & 23 deletions packages/client/test/rpc/engine/newPayloadV4.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ const [blockData] = beaconData

const parentBeaconBlockRoot = '0x42942949c4ed512cd85c2cb54ca88591338cbb0564d3a2bea7961a639ef29d64'
const validForkChoiceState = {
headBlockHash: '0x6abe4c2777a6a1e994d83920cfb95229b071174b95c89343f54b926f733789f2',
safeBlockHash: '0x6abe4c2777a6a1e994d83920cfb95229b071174b95c89343f54b926f733789f2',
finalizedBlockHash: '0x6abe4c2777a6a1e994d83920cfb95229b071174b95c89343f54b926f733789f2',
headBlockHash: '0x5bc7efe14c04eed7572809bb9c11d48d872139384097b95e04f8ab1b01ae8ecc',
safeBlockHash: '0x5bc7efe14c04eed7572809bb9c11d48d872139384097b95e04f8ab1b01ae8ecc',
finalizedBlockHash: '0x5bc7efe14c04eed7572809bb9c11d48d872139384097b95e04f8ab1b01ae8ecc',
}
const validPayloadAttributes = {
timestamp: '0x64ba84fd',
Expand All @@ -35,26 +35,24 @@ const electraGenesisContracts = {
// sender corresponding to the priv key 0x9c9996335451aab4fc4eac58e31a8c300e095cdbcee532d53d09280e83360355
'0x610adc49ecd66cbf176a8247ebd59096c031bd9f': { balance: '0x6d6172697573766477000000' },
// eip 2925 contract
'0x0aae40965e6800cd9b1f4b05ff21581047e3f91e': {
'0x0f792be4b0c0cb4dae440ef133e90c0ecd48cccc': {
balance: '0',
nonce: '1',
code: '0x3373fffffffffffffffffffffffffffffffffffffffe1460575767ffffffffffffffff5f3511605357600143035f3511604b575f35612000014311604b57611fff5f3516545f5260205ff35b5f5f5260205ff35b5f5ffd5b5f35611fff60014303165500',
code: '0x3373fffffffffffffffffffffffffffffffffffffffe14604657602036036042575f35600143038111604257611fff81430311604257611fff9006545f5260205ff35b5f5ffd5b5f35611fff60014303065500',
},
// consolidation requests contract
'0x00706203067988Ab3E2A2ab626EdCD6f28bDBbbb': {
balance: '0',
nonce: '1',
code: '0x3373fffffffffffffffffffffffffffffffffffffffe1460cf573615156028575f545f5260205ff35b366060141561019a5760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1461019a57600182026001905f5b5f821115608057810190830284830290049160010191906065565b90939004341061019a57600154600101600155600354806004026004013381556001015f358155600101602035815560010160403590553360601b5f5260605f60143760745fa0600101600355005b6003546002548082038060011160e3575060015b5f5b8181146101295780607402838201600402600401805490600101805490600101805490600101549260601b84529083601401528260340152906054015260010160e5565b910180921461013b5790600255610146565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff141561017357505f5b6001546001828201116101885750505f61018e565b01600190035b5f555f6001556074025ff35b5f5ffd',
'0x00431f263ce400f4455c2dcf564e53007ca4bbbb': {
nonce: '0x01',
balance: '0x00',
code: '0x3373fffffffffffffffffffffffffffffffffffffffe1460d35760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1461019a57600182026001905f5b5f82111560685781019083028483029004916001019190604d565b9093900492505050366060146088573661019a573461019a575f5260205ff35b341061019a57600154600101600155600354806004026004013381556001015f358155600101602035815560010160403590553360601b5f5260605f60143760745fa0600101600355005b6003546002548082038060021160e7575060025b5f5b8181146101295782810160040260040181607402815460601b815260140181600101548152602001816002015481526020019060030154905260010160e9565b910180921461013b5790600255610146565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff141561017357505f5b6001546001828201116101885750505f61018e565b01600190035b5f555f6001556074025ff35b5f5ffd',
storage: {},
},
// withdrawals request contract
'0x05F27129610CB42103b665629CB5c8C00296AaAa': {
balance: '0',
nonce: '1',
code: '0x3373fffffffffffffffffffffffffffffffffffffffe1460c7573615156028575f545f5260205ff35b36603814156101f05760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff146101f057600182026001905f5b5f821115608057810190830284830290049160010191906065565b9093900434106101f057600154600101600155600354806003026004013381556001015f35815560010160203590553360601b5f5260385f601437604c5fa0600101600355005b6003546002548082038060101160db575060105b5f5b81811461017f5780604c02838201600302600401805490600101805490600101549160601b83528260140152807fffffffffffffffffffffffffffffffff0000000000000000000000000000000016826034015260401c906044018160381c81600701538160301c81600601538160281c81600501538160201c81600401538160181c81600301538160101c81600201538160081c81600101535360010160dd565b9101809214610191579060025561019c565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14156101c957505f5b6001546002828201116101de5750505f6101e4565b01600290035b5f555f600155604c025ff35b5f5ffd',
storage: {
'0x0000000000000000000000000000000000000000000000000000000000000000':
'0x000000000000000000000000000000000000000000000000000000000000049d',
},
'0x0c15f14308530b7cdb8460094bbb9cc28b9aaaaa': {
nonce: '0x01',
balance: '0x00',
code: '0x3373fffffffffffffffffffffffffffffffffffffffe1460cb5760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff146101f457600182026001905f5b5f82111560685781019083028483029004916001019190604d565b909390049250505036603814608857366101f457346101f4575f5260205ff35b34106101f457600154600101600155600354806003026004013381556001015f35815560010160203590553360601b5f5260385f601437604c5fa0600101600355005b6003546002548082038060101160df575060105b5f5b8181146101835782810160030260040181604c02815460601b8152601401816001015481526020019060020154807fffffffffffffffffffffffffffffffff00000000000000000000000000000000168252906010019060401c908160381c81600701538160301c81600601538160281c81600501538160201c81600401538160181c81600301538160101c81600201538160081c81600101535360010160e1565b910180921461019557906002556101a0565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14156101cd57505f5b6001546002828201116101e25750505f6101e8565b01600290035b5f555f600155604c025ff35b5f5ffd',
storage: {},
},
// beacon deposit contract for deposit receipts
'0x00000000219ab540356cBB839Cbe05303d7705Fa': {
Expand Down Expand Up @@ -160,9 +158,9 @@ describe(`${method}: call with executionPayloadV4`, () => {
withdrawals: [],
blobGasUsed: '0x0',
excessBlobGas: '0x0',
parentHash: '0x6abe4c2777a6a1e994d83920cfb95229b071174b95c89343f54b926f733789f2',
stateRoot: '0x7aa6e46df1f78988a3141b5e7da8abee78d1daca175f43fe8866b2d1bf8d8ef8',
blockHash: '0x9a5903d803e6e7c3631cd76cb7279f93d7facc995c53eaffadf4e225504b18eb',
parentHash: '0x5bc7efe14c04eed7572809bb9c11d48d872139384097b95e04f8ab1b01ae8ecc',
stateRoot: '0xebe157ea5c3dc6fb5970f67b76266903282aee9772030f06c112348f32037fd9',
blockHash: '0x725c21032b68ae7d2f143581d0196cfbfd14dbc45c14eaeab15443831de489b7',
}

const oldMethods = ['engine_newPayloadV1', 'engine_newPayloadV2', 'engine_newPayloadV3']
Expand All @@ -180,7 +178,7 @@ describe(`${method}: call with executionPayloadV4`, () => {
assert.ok(res.error.message.includes(expectedError))
}

res = await rpc.request(method, [validBlock, [], parentBeaconBlockRoot, ['0x', '0x', '0x']])
res = await rpc.request(method, [validBlock, [], parentBeaconBlockRoot, []])
assert.equal(res.result.status, 'VALID')

res = await rpc.request('engine_forkchoiceUpdatedV3', validPayload)
Expand All @@ -201,9 +199,20 @@ describe(`${method}: call with executionPayloadV4`, () => {

res = await rpc.request('engine_getPayloadV4', [payloadId])
const { executionPayload, executionRequests } = res.result

assert.ok(
executionRequests?.length === 1,
'executionRequests should have the deposit request, and should exclude the other requests (these are empty)',
)

const depositRequestBytes = hexToBytes(executionRequests[0])
assert.ok(
depositRequestBytes[0] === 0x00,
'deposit request byte 0 is the deposit request identifier byte (0x00)',
)
assert.ok(
executionRequests?.length === 3,
'executionRequests should have 3 entries for each request type',
depositRequestBytes.length > 1,
'deposit request includes data (and is thus not empty)',
)

res = await rpc.request(method, [
Expand Down
18 changes: 18 additions & 0 deletions packages/common/src/eips.ts
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,15 @@ export const eipsDict: EIPsDict = {
*/
requiredEIPs: [3540, 3541, 3670],
},
/**
* Description : Increase calldata cost to reduce maximum block size
* URL : https://github.com/ethereum/EIPs/blob/da2a86bf15044416e8eb0301c9bdb8d561feeb32/EIPS/eip-7623.md
* Status : Review
*/
7623: {
minimumHardfork: Hardfork.Chainstart,
requiredEIPs: [],
},
/**
* Description : General purpose execution layer requests
* URL : https://eips.ethereum.org/EIPS/eip-7685
Expand All @@ -415,6 +424,15 @@ export const eipsDict: EIPsDict = {
minimumHardfork: Hardfork.Cancun,
requiredEIPs: [3675],
},
/**
* Description : Blob throughput increase
* URL : https://eips.ethereum.org/EIPS/eip-7691
* Status : Review
*/
7691: {
minimumHardfork: Hardfork.Paris,
requiredEIPs: [4844],
},
/**
* Description : EVM Object Format (EOFv1) Meta
* URL : https://github.com/ethereum/EIPs/blob/4153e95befd0264082de3c4c2fe3a85cc74d3152/EIPS/eip-7692.md
Expand Down
4 changes: 2 additions & 2 deletions packages/common/src/hardforks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,10 @@ export const hardforksDict: HardforksDict = {
* Status : Final
*/
prague: {
eips: [2537, 2935, 6110, 7002, 7251, 7685, 7702], // This is current prague without EOF
eips: [2537, 2935, 6110, 7002, 7251, 7623, 7685, 7691, 7702],
},
osaka: {
eips: [663, 3540, 3670, 4200, 4750, 5450, 6206, 7069, 7480, 7620, 7692, 7698], // These are the EOF EIPs
eips: [663, 3540, 3670, 4200, 4750, 5450, 6206, 7069, 7480, 7620, 7692, 7698],
},
/**
* Description: Next feature hardfork after prague, internally used for verkle testing/implementation (incomplete/experimental)
Expand Down
2 changes: 1 addition & 1 deletion packages/evm/src/evm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ export class EVM implements EVMInterface {
const supportedEIPs = [
663, 1153, 1559, 2537, 2565, 2718, 2929, 2930, 2935, 3198, 3529, 3540, 3541, 3607, 3651, 3670,
3855, 3860, 4200, 4399, 4750, 4788, 4844, 4895, 5133, 5450, 5656, 6110, 6206, 6780, 6800,
7002, 7069, 7251, 7480, 7516, 7620, 7685, 7692, 7698, 7702, 7709,
7002, 7069, 7251, 7480, 7516, 7620, 7685, 7691, 7692, 7698, 7702, 7709,
]

for (const eip of this.common.eips()) {
Expand Down
Loading

0 comments on commit 99cfdd6

Please sign in to comment.