Skip to content

Commit a58c6cb

Browse files
Fix Blake2F gas + output calculation on non-zero aligned inputs (#3201)
* refactor(precompiles/09-blake2f.ts): improve readability and performance by using DataView with byteOffset instead of subarray The changes in this commit refactor the code in the `precompile09` function in the `09-blake2f.ts` file. The changes improve the readability and performance of the code by using the `DataView` constructor with `byteOffset` instead of using `subarray` to create new `DataView` instances. Before the changes: - The `rounds`, `hRaw`, `mRaw`, and `tRaw` variables were created using `subarray` to extract specific parts of the `data` array buffer. - The `subarray` method was used with specific indices to create new `DataView` instances. After the changes: - The `rounds`, `hRaw`, `mRaw`, and `tRaw` variables are created using the `DataView` constructor with `byteOffset` to directly access the desired parts of the `data` array buffer. - The `DataView` constructor is used with the appropriate `byteOffset` values to create new `DataView` instances. These changes improve the readability of the code by making it clearer which parts of the `data` array buffer are being accessed. Additionally, using `DataView` with `byteOffset` instead of `subarray` can improve performance by avoiding unnecessary memory allocations. * evm: add blake2f test * evm: blake2f test: add extra comment * evm: fix blake2f "it.only" --------- Co-authored-by: Jochem Brouwer <[email protected]>
1 parent 44e069e commit a58c6cb

File tree

2 files changed

+39
-5
lines changed

2 files changed

+39
-5
lines changed

packages/evm/src/precompiles/09-blake2f.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,10 @@ export function precompile09(opts: PrecompileInput): ExecResult {
181181
}
182182
}
183183

184-
const rounds = new DataView(data.subarray(0, 4).buffer).getUint32(0)
185-
const hRaw = new DataView(data.buffer, 4, 64)
186-
const mRaw = new DataView(data.buffer, 68, 128)
187-
const tRaw = new DataView(data.buffer, 196, 16)
184+
const rounds = new DataView(data.buffer, data.byteOffset).getUint32(0)
185+
const hRaw = new DataView(data.buffer, data.byteOffset + 4, 64)
186+
const mRaw = new DataView(data.buffer, data.byteOffset + 68, 128)
187+
const tRaw = new DataView(data.buffer, data.byteOffset + 196, 16)
188188
// final
189189
const f = lastByte === 1
190190

packages/evm/test/precompiles/09-blake2f.spec.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Chain, Common, Hardfork } from '@ethereumjs/common'
2-
import { bytesToHex, hexToBytes } from '@ethereumjs/util'
2+
import { Address, bytesToHex, hexToBytes } from '@ethereumjs/util'
33
import { assert, describe, it } from 'vitest'
44

55
import { EVM, getActivePrecompiles } from '../../src/index.js'
@@ -114,4 +114,38 @@ describe('Precompiles: BLAKE2F', () => {
114114
assert.equal(result.exceptionError?.error, t.expectedError, 'should generate expected error')
115115
})
116116
}
117+
118+
it('should also work on non-zero aligned inputs', async () => {
119+
const addr = Address.zero()
120+
// Blake2f calldata from https://etherscan.io/tx/0x4f2e13a0a3f14033630ab2b8cdad09d316826375f761ded5b31253bb42e0a476
121+
// (This tx calls into Blake2f multiple times, but one of them is taken)
122+
const calldata =
123+
'0x0000000c28c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b3dd8338ed89de6791854126751ac933302810c04147014e9eb472e4dbc09d3c96abb531c9ae39c9e6c454cb83913d688795e237837d30258d11ea7c75201003000454cb83913d688795e237837d30258d11ea7c752011af5b8015c64d39ab44c60ead8317f9f5a9b6c4c01000000000100ca9a3b000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000'
124+
125+
// This code:
126+
// -> Copies the CALLDATA into memory, but at offset 0x20 (32)
127+
// -> Calls Blake2F with this data (so, with the calldata)
128+
// -> Returns the data from Blake2F
129+
const code = '0x366000602037' + '600080366020600060095AF1593D6000593E3D90F3'
130+
await evm.stateManager.putContractCode(addr, hexToBytes(code))
131+
132+
const res = await evm.runCall({
133+
data: hexToBytes(calldata),
134+
to: addr,
135+
})
136+
137+
/*
138+
Note: this value is retrieved from infura by calling directly into Blake2F with the above `calldata`:
139+
140+
curl https://mainnet.infura.io/v3/API_KEY_HERE \
141+
-X POST \
142+
-H "Content-Type: application/json" \
143+
-d '{"jsonrpc":"2.0","method":"eth_call","params": [{"to": "0x0000000000000000000000000000000000000009","data": "0x0000000c28c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b3dd8338ed89de6791854126751ac933302810c04147014e9eb472e4dbc09d3c96abb531c9ae39c9e6c454cb83913d688795e237837d30258d11ea7c75201003000454cb83913d688795e237837d30258d11ea7c752011af5b8015c64d39ab44c60ead8317f9f5a9b6c4c01000000000100ca9a3b000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000"}, "latest"],"id":1}'
144+
*/
145+
146+
const expected =
147+
'0x772acbd3f30b0c3f5f53e8b836ab406f7d8d46fd4b27e2ce2ecd67dbf18c958741e2c49d1f1b1a463907a484f970c057dab9684062b82fda69e8a0057e14766f'
148+
149+
assert.equal(bytesToHex(res.execResult.returnValue), expected)
150+
})
117151
})

0 commit comments

Comments
 (0)