@tokamak-zk-evm/synthesizer
Version:
Tokamak zk-EVM Synthesizer - Processes Ethereum transactions into wire maps for Tokamak zk-SNARK proof generation
79 lines (68 loc) • 2.18 kB
text/typescript
import {
BIGINT_27,
BIGINT_28,
bytesToBigInt,
bytesToHex,
ecrecover,
publicToAddress,
setLengthLeft,
setLengthRight,
} from "@synthesizer-libs/util"
import { OOGResult } from '../evm.js'
import { gasLimitCheck } from './util.js'
import { getPrecompileName } from './index.js'
import type { ExecResult } from '../types.js'
import type { PrecompileInput } from './types.js'
export function precompile01(opts: PrecompileInput): ExecResult {
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)
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 (e: any) {
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,
}
}