Key Rotation and Recovery
Key rotation and recovery on the keystore
Key rotation is the process of updating the data
in the (data, vkey)
pair at a keystoreAddress
which is done by executing an UPDATE
transaction on the keystore. The UPDATE
transaction is serialized in the following format:
Here, the fields are given by:
bool isL1Initiated
: Whether the transaction is L1-initiated.bytes l1InitiatedNonce
: Represents theuint256
L1-initiated nonce for the transaction if the transaction is L1-initiated and the empty bytestringbytes(0x)
otherwise.uint256 nonce
: The nonce for the transaction.- Can be set with the result from the
keystore_getTransactionCount
RPC endpoint.
- Can be set with the result from the
bytes feePerGas
: Represents theuint256
fee per gas for the transaction if the transaction is not L1-initiated and the empty bytestringbytes(0x)
otherwise.- An estimate for this value can be obtained from the
keystore_gasPrice
RPC endpoint.
- An estimate for this value can be obtained from the
bytes newUserData
: The new user data to update to.bytes newUserVkey
: The new user vkey to update to.KeystoreAccount userAcct
: The user account paying for the transaction.bytes userProof
: The user’s ZK authentication proof for the transaction.bytes sponsorAcctBytes
: Represents the RLP-encodedKeystoreAccount
of the sponsor account sponsoring the transaction if the transaction is sponsored and the empty bytestringbytes(0x)
otherwise.bytes sponsorProof
: Represents the sponsor’s ZK authentication proof sponsoring the transaction if the transaction is sponsored and the empty bytestringbytes(0x)
otherwise.
Then, the serialized transaction can be sent to the sequencer via the keystore_sendRawTransaction
RPC endpoint.
Cost of a Key Rotation
The cost of a key rotation is the fee for the UPDATE
transaction for the specific newUserData
and newUserVkey
values. Further details on computing this cost can be found in Transaction Fees.
ZK Authentication
Instead of relying on a single signature scheme to authenticate transactions, the keystore uses ZK proofs to allow wrapping of arbitrary authentication logic exposed through a universal interface. The userProof
and sponsorProof
take (userMsgHash
, userDataHash
) and (sponsorMsgHash
, sponsorDataHash
) as public inputs, respectively, where the msgHash
es commit to relevant parameters of the transaction which allows verifying that the public key data committed to by dataHash
es are consistent with the signers of the msgHash
es.
Creating the Message Hash
To maximize compatibility with the existing Ethereum wallet ecosystem, the UPDATE
transaction msgHash
es conform to the EIP-712 specification. Here are the relevant EIP-712 parameters:
Updates specifically will require the UPDATE_TYPEHASH
.
Sponsors will also sign an EIP-712 payload using the same parameters as above but with the SPONSOR_TYPEHASH
instead.
msgHash
es can be calculated according to the EIP-712 specification.
ZK Authentication Proof Generation
Generating ZK proofs for transaction authentication is currently resource-intensive. As a result, to improve UX and transaction latency, we introduce a new entity into the system: the signature prover. This entity is expected to run robust, high-performance machines capable of generating ZK proofs efficiently to authenticate user transactions on the keystore.
You can read more in Signature Provers.
Send an Update Transaction with the SDK
We provide a Typescript SDK for helping interacting with the keystore. You can find an example of a key rotation using this SDK here.
Latency
The total latency of a key rotation being usable on L2 can be broken down into three phases:
-
Proof Generation: The total time it takes for the signature prover to generate the ZK proof(s) for a transaction. Even though sponsored transactions have two proofs, since the user and sponsor proofs are generated in parallel, the latency is the same as a non-sponsored transaction. As of the most recent release, the proof generation latency is ~6 min.
-
Transaction Finalization: The total time from submission of a transaction to the sequencer until finalization on the L1 bridge. This is (most of the time) upper bounded by the prover’s finalization interval which is around once per hour.
-
L2 Ingestion of L1 State: The time from the mining of an L1 block to an L2 actually becoming aware of the state in that L1 block. In OP Stack rollups, the sequencer can choose how closely the L2 follows the L1 chain, which in the worst case may lead to delays of up to 12 hours. However, for the most part, the L2 typically lags by only about 10–32 blocks, corresponding to an actual delay of around 2–7 minutes.
Combining these three phases, once a user broadcasts their intent to rotate a key, the updated permission set should usually be available for use on L2 in 1-1.5 hours.