Skip to content

Commit 846fea7

Browse files
vm/eip6110: log layout check (#3977)
* vm/eip6110: log layout check * vm: eip6110 update deposits layout verifier
1 parent 1cbcd6a commit 846fea7

File tree

1 file changed

+59
-11
lines changed

1 file changed

+59
-11
lines changed

packages/vm/src/requests.ts

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import {
55
EthereumJSErrorWithoutCode,
66
bigIntToAddressBytes,
77
bigIntToBytes,
8+
bytesToBigInt,
89
bytesToHex,
9-
bytesToInt,
1010
concatBytes,
1111
createAddressFromString,
1212
setLengthLeft,
@@ -16,6 +16,18 @@ import type { RunTxResult } from './types.ts'
1616
import type { VM } from './vm.ts'
1717

1818
const DEPOSIT_TOPIC = '0x649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5'
19+
const PUBKEY_OFFSET = BigInt(160)
20+
const WITHDRAWAL_CREDENTIALS_OFFSET = BigInt(256)
21+
const AMOUNT_OFFSET = BigInt(320)
22+
const SIGNATURE_OFFSET = BigInt(384)
23+
const INDEX_OFFSET = BigInt(512)
24+
const PUBKEY_SIZE = BigInt(48)
25+
const WITHDRAWAL_CREDENTIALS_SIZE = BigInt(32)
26+
const AMOUNT_SIZE = BigInt(8)
27+
const SIGNATURE_SIZE = BigInt(96)
28+
const INDEX_SIZE = BigInt(8)
29+
const LOG_SIZE = 576
30+
const LOG_LAYOUT_MISMATCH = 'invalid deposit log: unsupported data layout'
1931

2032
/**
2133
* This helper method generates a list of all CL requests that can be included in a pending block
@@ -158,6 +170,9 @@ const accumulateDepositsRequest = (
158170
}
159171

160172
function parseDepositLog(requestData: Uint8Array) {
173+
if (requestData.length !== LOG_SIZE) {
174+
throw EthereumJSErrorWithoutCode(LOG_LAYOUT_MISMATCH)
175+
}
161176
// Extracts validator pubkey, withdrawal credential, deposit amount, signature,
162177
// and validator index from Deposit Event log.
163178
// The event fields are non-indexed so contained in one byte array (log[2]) so parsing is as follows:
@@ -166,18 +181,51 @@ function parseDepositLog(requestData: Uint8Array) {
166181
// 3. Read 32 bytes starting with the first field position to get the size of the first field
167182
// 4. Read the bytes from first field position + 32 + the size of the first field to get the first field value
168183
// 5. Repeat steps 3-4 for each field
169-
const pubKeyIdx = bytesToInt(requestData.slice(0, 32))
170-
const pubKeySize = bytesToInt(requestData.slice(pubKeyIdx, pubKeyIdx + 32))
171-
const withdrawalCreditsIdx = bytesToInt(requestData.slice(32, 64))
172-
const withdrawalCreditsSize = bytesToInt(
184+
const pubKeyIdxBigInt = bytesToBigInt(requestData.slice(0, 32))
185+
const withdrawalCreditsIdxBigInt = bytesToBigInt(requestData.slice(32, 64))
186+
const amountIdxBigInt = bytesToBigInt(requestData.slice(64, 96))
187+
const sigIdxBigInt = bytesToBigInt(requestData.slice(96, 128))
188+
const indexIdxBigInt = bytesToBigInt(requestData.slice(128, 160))
189+
190+
if (
191+
pubKeyIdxBigInt !== PUBKEY_OFFSET ||
192+
withdrawalCreditsIdxBigInt !== WITHDRAWAL_CREDENTIALS_OFFSET ||
193+
amountIdxBigInt !== AMOUNT_OFFSET ||
194+
sigIdxBigInt !== SIGNATURE_OFFSET ||
195+
indexIdxBigInt !== INDEX_OFFSET
196+
) {
197+
throw EthereumJSErrorWithoutCode(LOG_LAYOUT_MISMATCH)
198+
}
199+
200+
const pubKeyIdx = Number(pubKeyIdxBigInt)
201+
const withdrawalCreditsIdx = Number(withdrawalCreditsIdxBigInt)
202+
const amountIdx = Number(amountIdxBigInt)
203+
const sigIdx = Number(sigIdxBigInt)
204+
const indexIdx = Number(indexIdxBigInt)
205+
206+
const pubKeySizeBigInt = bytesToBigInt(requestData.slice(pubKeyIdx, pubKeyIdx + 32))
207+
const withdrawalCreditsSizeBigInt = bytesToBigInt(
173208
requestData.slice(withdrawalCreditsIdx, withdrawalCreditsIdx + 32),
174209
)
175-
const amountIdx = bytesToInt(requestData.slice(64, 96))
176-
const amountSize = bytesToInt(requestData.slice(amountIdx, amountIdx + 32))
177-
const sigIdx = bytesToInt(requestData.slice(96, 128))
178-
const sigSize = bytesToInt(requestData.slice(sigIdx, sigIdx + 32))
179-
const indexIdx = bytesToInt(requestData.slice(128, 160))
180-
const indexSize = bytesToInt(requestData.slice(indexIdx, indexIdx + 32))
210+
const amountSizeBigInt = bytesToBigInt(requestData.slice(amountIdx, amountIdx + 32))
211+
const sigSizeBigInt = bytesToBigInt(requestData.slice(sigIdx, sigIdx + 32))
212+
const indexSizeBigInt = bytesToBigInt(requestData.slice(indexIdx, indexIdx + 32))
213+
214+
if (
215+
pubKeySizeBigInt !== PUBKEY_SIZE ||
216+
withdrawalCreditsSizeBigInt !== WITHDRAWAL_CREDENTIALS_SIZE ||
217+
amountSizeBigInt !== AMOUNT_SIZE ||
218+
sigSizeBigInt !== SIGNATURE_SIZE ||
219+
indexSizeBigInt !== INDEX_SIZE
220+
) {
221+
throw EthereumJSErrorWithoutCode(LOG_LAYOUT_MISMATCH)
222+
}
223+
224+
const pubKeySize = Number(pubKeySizeBigInt)
225+
const withdrawalCreditsSize = Number(withdrawalCreditsSizeBigInt)
226+
const amountSize = Number(amountSizeBigInt)
227+
const sigSize = Number(sigSizeBigInt)
228+
const indexSize = Number(indexSizeBigInt)
181229

182230
const pubkey = requestData.slice(pubKeyIdx + 32, pubKeyIdx + 32 + pubKeySize)
183231
const withdrawalCredentials = requestData.slice(

0 commit comments

Comments
 (0)