Skip to content

Commit 5fe681b

Browse files
committed
modify the deposit, withdrawal and consolidation requests accumulation for buildblock and runblock and corresponding requestsroot calcs
1 parent 5d2ede2 commit 5fe681b

File tree

3 files changed

+35
-96
lines changed

3 files changed

+35
-96
lines changed

packages/vm/src/buildBlock.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -347,8 +347,7 @@ export class BlockBuilder {
347347
if (this.vm.common.isActivatedEIP(7685)) {
348348
const sha256Function = this.vm.common.customCrypto.sha256 ?? sha256
349349
requests = await accumulateRequests(this.vm, this.transactionResults)
350-
requestsRoot = await genRequestsRoot(requests, sha256Function)
351-
// Do other validations per request type
350+
requestsRoot = genRequestsRoot(requests, sha256Function)
352351
}
353352

354353
// get stateRoot after all the accumulateRequests etc have been done
@@ -376,7 +375,6 @@ export class BlockBuilder {
376375
header: headerData,
377376
transactions: this.transactions,
378377
withdrawals: this.withdrawals,
379-
requests,
380378
}
381379

382380
let block
@@ -397,7 +395,7 @@ export class BlockBuilder {
397395
this.checkpointed = false
398396
}
399397

400-
return block
398+
return { block, requests }
401399
}
402400

403401
async initState() {

packages/vm/src/requests.ts

Lines changed: 24 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,13 @@ import {
33
bigIntToAddressBytes,
44
bigIntToBytes,
55
bytesToHex,
6-
bytesToInt,
76
createAddressFromString,
8-
createConsolidationRequest,
9-
createDepositRequest,
10-
createWithdrawalRequest,
117
setLengthLeft,
128
} from '@ethereumjs/util'
139

10+
import { concatBytes } from '../../util/src/bytes.js'
11+
import { ConsolidationRequest, DepositRequest, WithdrawalRequest } from '../../util/src/request.js'
12+
1413
import type { RunTxResult } from './types.js'
1514
import type { VM } from './vm.js'
1615
import type { CLRequest, CLRequestType } from '@ethereumjs/util'
@@ -33,30 +32,27 @@ export const accumulateRequests = async (
3332
vm.common['_chainParams'].depositContractAddress ?? Mainnet.depositContractAddress
3433
if (depositContractAddress === undefined)
3534
throw new Error('deposit contract address required with EIP 6110')
36-
await accumulateDeposits(depositContractAddress, txResults, requests)
35+
const depositsRequest = accumulateDepositsRequest(depositContractAddress, txResults)
36+
requests.push(depositsRequest)
3737
}
3838

3939
if (common.isActivatedEIP(7002)) {
40-
await accumulateEIP7002Requests(vm, requests)
40+
const withdrawalsRequest = await accumulateWithdrawalsRequest(vm)
41+
requests.push(withdrawalsRequest)
4142
}
4243

4344
if (common.isActivatedEIP(7251)) {
44-
await accumulateEIP7251Requests(vm, requests)
45+
const consolidationsRequest = await accumulateConsolidationsRequest(vm)
46+
requests.push(consolidationsRequest)
4547
}
4648

47-
if (requests.length > 1) {
48-
for (let x = 1; x < requests.length; x++) {
49-
if (requests[x].type < requests[x - 1].type)
50-
throw new Error('requests are not in ascending order')
51-
}
52-
}
49+
// requests are already type byte ordered by construction
5350
return requests
5451
}
5552

56-
const accumulateEIP7002Requests = async (
53+
const accumulateWithdrawalsRequest = async (
5754
vm: VM,
58-
requests: CLRequest<CLRequestType>[],
59-
): Promise<void> => {
55+
): Promise<CLRequest<CLRequestType.Withdrawal>> => {
6056
// Partial withdrawals logic
6157
const addressBytes = setLengthLeft(
6258
bigIntToBytes(vm.common.param('withdrawalRequestPredeployAddress')),
@@ -71,7 +67,7 @@ const accumulateEIP7002Requests = async (
7167
const originalAccount = await vm.stateManager.getAccount(withdrawalsAddress)
7268

7369
if (originalAccount === undefined) {
74-
return
70+
return new WithdrawalRequest(new Uint8Array())
7571
}
7672

7773
const results = await vm.evm.runCall({
@@ -87,22 +83,12 @@ const accumulateEIP7002Requests = async (
8783
}
8884

8985
const resultsBytes = results.execResult.returnValue
90-
if (resultsBytes.length > 0) {
91-
// Each request is 76 bytes
92-
for (let startByte = 0; startByte < resultsBytes.length; startByte += 76) {
93-
const slicedBytes = resultsBytes.slice(startByte, startByte + 76)
94-
const sourceAddress = slicedBytes.slice(0, 20) // 20 Bytes
95-
const validatorPubkey = slicedBytes.slice(20, 68) // 48 Bytes
96-
const amount = slicedBytes.slice(68, 76) // 8 Bytes / Uint64 LE
97-
requests.push(createWithdrawalRequest({ sourceAddress, validatorPubkey, amount }))
98-
}
99-
}
86+
return new WithdrawalRequest(resultsBytes)
10087
}
10188

102-
const accumulateEIP7251Requests = async (
89+
const accumulateConsolidationsRequest = async (
10390
vm: VM,
104-
requests: CLRequest<CLRequestType>[],
105-
): Promise<void> => {
91+
): Promise<CLRequest<CLRequestType.Consolidation>> => {
10692
// Partial withdrawals logic
10793
const addressBytes = setLengthLeft(
10894
bigIntToBytes(vm.common.param('consolidationRequestPredeployAddress')),
@@ -117,7 +103,7 @@ const accumulateEIP7251Requests = async (
117103
const originalAccount = await vm.stateManager.getAccount(consolidationsAddress)
118104

119105
if (originalAccount === undefined) {
120-
return
106+
return new ConsolidationRequest(new Uint8Array(0))
121107
}
122108

123109
const results = await vm.evm.runCall({
@@ -133,67 +119,22 @@ const accumulateEIP7251Requests = async (
133119
}
134120

135121
const resultsBytes = results.execResult.returnValue
136-
if (resultsBytes.length > 0) {
137-
// Each request is 116 bytes
138-
for (let startByte = 0; startByte < resultsBytes.length; startByte += 116) {
139-
const slicedBytes = resultsBytes.slice(startByte, startByte + 116)
140-
const sourceAddress = slicedBytes.slice(0, 20) // 20 Bytes
141-
const sourcePubkey = slicedBytes.slice(20, 68) // 48 Bytes
142-
const targetPubkey = slicedBytes.slice(68, 116) // 48 bytes
143-
requests.push(createConsolidationRequest({ sourceAddress, sourcePubkey, targetPubkey }))
144-
}
145-
}
122+
return new ConsolidationRequest(resultsBytes)
146123
}
147124

148-
const accumulateDeposits = async (
125+
const accumulateDepositsRequest = (
149126
depositContractAddress: string,
150127
txResults: RunTxResult[],
151-
requests: CLRequest<CLRequestType>[],
152-
) => {
128+
): CLRequest<CLRequestType.Deposit> => {
129+
let resultsBytes = new Uint8Array(0)
153130
for (const [_, tx] of txResults.entries()) {
154131
for (let i = 0; i < tx.receipt.logs.length; i++) {
155132
const log = tx.receipt.logs[i]
156133
if (bytesToHex(log[0]).toLowerCase() === depositContractAddress.toLowerCase()) {
157-
// Extracts validator pubkey, withdrawal credential, deposit amount, signature,
158-
// and validator index from Deposit Event log.
159-
// The event fields are non-indexed so contained in one byte array (log[2]) so parsing is as follows:
160-
// 1. Read the first 32 bytes to get the starting position of the first field.
161-
// 2. Continue reading the byte array in 32 byte increments to get all the field starting positions
162-
// 3. Read 32 bytes starting with the first field position to get the size of the first field
163-
// 4. Read the bytes from first field position + 32 + the size of the first field to get the first field value
164-
// 5. Repeat steps 3-4 for each field
165-
const pubKeyIdx = bytesToInt(log[2].slice(0, 32))
166-
const pubKeySize = bytesToInt(log[2].slice(pubKeyIdx, pubKeyIdx + 32))
167-
const withdrawalCreditsIdx = bytesToInt(log[2].slice(32, 64))
168-
const withdrawalCreditsSize = bytesToInt(
169-
log[2].slice(withdrawalCreditsIdx, withdrawalCreditsIdx + 32),
170-
)
171-
const amountIdx = bytesToInt(log[2].slice(64, 96))
172-
const amountSize = bytesToInt(log[2].slice(amountIdx, amountIdx + 32))
173-
const sigIdx = bytesToInt(log[2].slice(96, 128))
174-
const sigSize = bytesToInt(log[2].slice(sigIdx, sigIdx + 32))
175-
const indexIdx = bytesToInt(log[2].slice(128, 160))
176-
const indexSize = bytesToInt(log[2].slice(indexIdx, indexIdx + 32))
177-
178-
const pubkey = log[2].slice(pubKeyIdx + 32, pubKeyIdx + 32 + pubKeySize)
179-
const withdrawalCredentials = log[2].slice(
180-
withdrawalCreditsIdx + 32,
181-
withdrawalCreditsIdx + 32 + withdrawalCreditsSize,
182-
)
183-
const amount = log[2].slice(amountIdx + 32, amountIdx + 32 + amountSize)
184-
const signature = log[2].slice(sigIdx + 32, sigIdx + 32 + sigSize)
185-
const index = log[2].slice(indexIdx + 32, indexIdx + 32 + indexSize)
186-
187-
requests.push(
188-
createDepositRequest({
189-
pubkey,
190-
withdrawalCredentials,
191-
amount,
192-
signature,
193-
index,
194-
}),
195-
)
134+
resultsBytes = concatBytes(resultsBytes, log[2])
196135
}
197136
}
198137
}
138+
139+
return new DepositRequest(resultsBytes)
199140
}

packages/vm/src/runBlock.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import {
2626
unprefixedHexToBytes,
2727
} from '@ethereumjs/util'
2828
import debugDefault from 'debug'
29-
import { keccak256 } from 'ethereum-cryptography/keccak.js'
3029
import { sha256 } from 'ethereum-cryptography/sha256'
3130

3231
import { Bloom } from './bloom/index.js'
@@ -219,7 +218,7 @@ export async function runBlock(vm: VM, opts: RunBlockOpts): Promise<RunBlockResu
219218
if (block.common.isActivatedEIP(7685)) {
220219
const sha256Function = vm.common.customCrypto.sha256 ?? sha256
221220
requests = await accumulateRequests(vm, result.results)
222-
requestsRoot = await genRequestsRoot(requests, sha256Function)
221+
requestsRoot = genRequestsRoot(requests, sha256Function)
223222
}
224223

225224
// Persist state
@@ -234,13 +233,13 @@ export async function runBlock(vm: VM, opts: RunBlockOpts): Promise<RunBlockResu
234233
// values to the current block, or validate the resulting
235234
// header values against the current block.
236235
if (generateFields) {
237-
const bloom = result.bloom.bitvector
236+
const logsBloom = result.bloom.bitvector
238237
const gasUsed = result.gasUsed
239238
const receiptTrie = result.receiptsRoot
240239
const transactionsTrie = await _genTxTrie(block)
241240
const generatedFields = {
242241
stateRoot,
243-
bloom,
242+
logsBloom,
244243
gasUsed,
245244
receiptTrie,
246245
transactionsTrie,
@@ -254,20 +253,21 @@ export async function runBlock(vm: VM, opts: RunBlockOpts): Promise<RunBlockResu
254253
block = createBlock(blockData, { common: vm.common })
255254
} else {
256255
if (vm.common.isActivatedEIP(7685)) {
257-
const valid = await block.requestsTrieIsValid(requests)
258-
if (!valid) {
259-
const keccakFunction = vm.common.customCrypto.keccak256 ?? keccak256
260-
const validRoot = await genRequestsRoot(requests!, keccakFunction)
256+
const sha256Function = vm.common.customCrypto.sha256 ?? sha256
257+
const requestsRoot = genRequestsRoot(requests!, sha256Function)
258+
259+
if (!equalsBytes(block.header.requestsRoot!, requestsRoot)) {
261260
if (vm.DEBUG)
262261
debug(
263262
`Invalid requestsRoot received=${bytesToHex(
264263
block.header.requestsRoot!,
265-
)} expected=${bytesToHex(validRoot)}`,
264+
)} expected=${bytesToHex(requestsRoot)}`,
266265
)
267266
const msg = _errorMsg('invalid requestsRoot', vm, block)
268267
throw new Error(msg)
269268
}
270269
}
270+
271271
if (!vm.common.isActivatedEIP(6800)) {
272272
// Only validate the following headers if verkle blocks aren't activated
273273
if (equalsBytes(result.receiptsRoot, block.header.receiptTrie) === false) {

0 commit comments

Comments
 (0)