UNPKG

@ethereumjs/evm

Version:
55 lines 2.22 kB
import { BIGINT_27, BIGINT_28, bytesToBigInt, bytesToHex, ecrecover, publicToAddress, setLengthLeft, setLengthRight, } from '@ethereumjs/util'; import { OOGResult } from "../evm.js"; import { getPrecompileName } from "./index.js"; import { gasLimitCheck } from "./util.js"; export function precompile01(opts) { const pName = getPrecompileName('01'); const ecrecoverFunction = opts.common.customCrypto.ecrecover ?? ecrecover; const gasUsed = opts.common.param('ecRecoverGas'); if (!gasLimitCheck(opts, gasUsed, pName)) { return OOGResult(opts.gasLimit); } const data = setLengthRight(opts.data, 128, { allowTruncate: true }); const msgHash = data.subarray(0, 32); const v = data.subarray(32, 64); const vBigInt = bytesToBigInt(v); // Guard against util's `ecrecover`: without providing chainId this will return // a signature in most of the cases in the cases that `v=0` or `v=1` // However, this should throw, only 27 and 28 is allowed as input if (vBigInt !== BIGINT_27 && vBigInt !== BIGINT_28) { if (opts._debug !== undefined) { opts._debug(`${pName} failed: v neither 27 nor 28`); } return { executionGasUsed: gasUsed, returnValue: new Uint8Array(), }; } const r = data.subarray(64, 96); const s = data.subarray(96, 128); let publicKey; try { if (opts._debug !== undefined) { opts._debug(`${pName}: PK recovery with msgHash=${bytesToHex(msgHash)} v=${bytesToHex(v)} r=${bytesToHex(r)}s=${bytesToHex(s)}}`); } publicKey = ecrecoverFunction(msgHash, bytesToBigInt(v), r, s); } catch { if (opts._debug !== undefined) { opts._debug(`${pName} failed: PK recovery failed`); } return { executionGasUsed: gasUsed, returnValue: new Uint8Array(0), }; } const address = setLengthLeft(publicToAddress(publicKey), 32); if (opts._debug !== undefined) { opts._debug(`${pName} return address=${bytesToHex(address)}`); } return { executionGasUsed: gasUsed, returnValue: address, }; } //# sourceMappingURL=01-ecrecover.js.map