ZK Account Authentication

Table of Contents

We authenticate transactions using zero-knowledge proofs instead of the usual ECDSA signature scheme. This allows the keystore to support arbitrary smart account types without additional protocol changes.

ZK Proof Format

We specify the authentication of a message hash msgHash against data committed to by dataHash using a verification key vkey for a halo2 circuit. A proof validating against vkey will establish the following statement:

Assuming the authentication is against data committed to by dataHash, there is valid authentication data to approve the message in msgHash.

To implement this, we require the public inputs PI(pf) to be a vector of length 4 forming a byte subarray of pf, with each element being 32 bytes and representing a value in the 254-bit scalar field of the BN254 curve. This vector should encode the following values:

PI(pf)[0:2] – hi-lo representation of bytes32 dataHash
PI(pf)[2:4] – hi-lo representation of bytes32 msgHash

To be explicit, we relate PI(pf) to pf by PI(pf)[i] = pf[384 + 32 * i : 384 + 32 * i + 32], and we say that bytes32 values (a, b) form a hi-lo representation of a bytes32 value c if a and b are 16 bytes and c = (a << 128) || b, i.e. a contains the top 16 bytes of c, and b contains the lower 16 bytes of c.

Account Authentication

To verify a ZK account authentication for msgHash, we perform the following check:

function authenticateMsg(bytes32 dataHash, bytes32 msgHash, bytes proof, bytes vkey) {
    require(PI(proof)[0:2] == dataHash);
    require(PI(proof)[2:4] == msgHash);
    require(proof is valid against vkey);
}

Example: 1-of-1 ECDSA Multisig

As an example, each L1 EOA can be associated with a 1-of-1 ECDSA multisig on the keystore as follows.

1-of-1 ECDSA multisig
=====================
Key:
* keccak256(salt, keccak256(eoa_addr), keccak256(vk))

Public IO:
* PI[0:2] -- dataHash
* PI[2:4] -- msgHash

Circuit statement:
* `keccak256(eoa_addr) == dataHash`
* there is an ECDSA signature for `msgHash` which verifies against `pub_key`
* `eoa_addr` corresponds to `pub_key`