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 inmsgHash
.
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`