Skip to content

Commit

Permalink
Update EIP 3074 AUTHCALL (#1867)
Browse files Browse the repository at this point in the history
* vm: update eip 3074

* vm: eip3074 test fixes start

* vm: fix eip3074 tests

* vm: expand eip3074 tests

* vm: add eip 3074 tests

* vm: address 128n -> BigInt(128)
  • Loading branch information
jochem-brouwer authored and g11tech committed Jun 3, 2022
1 parent c151338 commit c1f15c5
Show file tree
Hide file tree
Showing 4 changed files with 207 additions and 31 deletions.
2 changes: 1 addition & 1 deletion packages/vm/src/evm/opcodes/codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ const eipOpcodes: { eip: number; opcodes: OpcodeEntry }[] = [
{
eip: 3074,
opcodes: {
0xf6: { name: 'AUTH', isAsync: true, dynamicGas: false },
0xf6: { name: 'AUTH', isAsync: true, dynamicGas: true },
0xf7: { name: 'AUTHCALL', isAsync: true, dynamicGas: true },
},
},
Expand Down
40 changes: 32 additions & 8 deletions packages/vm/src/evm/opcodes/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
ecrecover,
publicToAddress,
SECP256K1_ORDER_DIV_2,
setLengthRight,
} from 'ethereumjs-util'
import {
addressToBuffer,
Expand Down Expand Up @@ -1023,33 +1024,56 @@ export const handlers: Map<number, OpHandler> = new Map([
[
0xf6,
async function (runState) {
const [commitUnpadded, yParity, r, s] = runState.stack.popN(4)
if (s > SECP256K1_ORDER_DIV_2) {
// eslint-disable-next-line prefer-const
let [authority, memOffset, memLength] = runState.stack.popN(3)

if (memLength > BigInt(128)) {
memLength = BigInt(128)
}

let mem = runState.memory.read(Number(memOffset), Number(memLength))
if (mem.length < 128) {
mem = setLengthRight(mem, 128)
}

const yParity = BigInt(mem[31])
const r = mem.slice(32, 64)
const s = mem.slice(64, 96)
const commit = mem.slice(96, 128)

if (bufferToBigInt(s) > SECP256K1_ORDER_DIV_2) {
trap(ERROR.AUTH_INVALID_S)
}

const commit = setLengthLeft(bigIntToBuffer(commitUnpadded), 32)
const paddedInvokerAddress = setLengthLeft(runState.eei._env.address.buf, 32)
const chainId = setLengthLeft(bigIntToBuffer(runState.eei.getChainId()), 32)
const message = Buffer.concat([EIP3074MAGIC, chainId, paddedInvokerAddress, commit])
const msgHash = Buffer.from(keccak256(message))

let recover
try {
recover = ecrecover(msgHash, Number(yParity) + 27, bigIntToBuffer(r), bigIntToBuffer(s))
recover = ecrecover(msgHash, Number(yParity) + 27, r, s)
} catch (e) {
// Malformed signature, push 0 on stack, clear auth variable and return
// Malformed signature, push 0 on stack, clear auth variable
runState.stack.push(BigInt(0))
runState.eei._env.auth = undefined
return
}

const addressBuffer = publicToAddress(recover)
const address = new Address(addressBuffer)
runState.eei._env.auth = address

const addressBigInt = bufferToBigInt(addressBuffer)
runState.stack.push(addressBigInt)
const expectedAddress = new Address(setLengthLeft(bigIntToBuffer(authority), 20))

if (!expectedAddress.equals(address)) {
// expected address does not equal the recovered address, clear auth variable
runState.stack.push(BigInt(0))
runState.eei._env.auth = undefined
return
}

runState.eei._env.auth = address
runState.stack.push(BigInt(1))
},
],
// 0xf7: AUTHCALL
Expand Down
9 changes: 9 additions & 0 deletions packages/vm/src/evm/opcodes/gas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,15 @@ export const dynamicGasHandlers: Map<number, AsyncDynamicGasHandler | SyncDynami
return gas
},
],
[
/* AUTH */
0xf6,
async function (runState, gas, common): Promise<bigint> {
const [_address, memOffset, memLength] = runState.stack.peek(3)
gas += subMemUsage(runState, memOffset, memLength, common)
return gas
},
],
[
/* AUTHCALL */
0xf7,
Expand Down
Loading

0 comments on commit c1f15c5

Please sign in to comment.