Keystore State and Addresses

Table of Contents

The keystore supports a read-write state, indexed by a new keystore address, and a write-only withdrawals state, indexed by withdrawal hash. We explain the address format and each state in this section.

Keystore Address Format

Addresses on the keystore are bytes32 values. They may be generated offchain using counterfactual initialization using the following parameters:

  • bytes32 salt - a salt to enable address uniqueness.
  • bytes initialData - the initial signing data associated with the address.
  • bytes initialVerificationData - computed as abi.encodePacked(initialExtraPvsHash, initialVkey)
    • bytes32 initialExtraPvsHash - the hash of the extra public values in the proof.
    • bytes initialVkey - the initial verification key for authenticating updates to the address.

The keystore address is then given by keystoreAddress = keccak256(salt, keccak256(initialData), keccak256(initialVerificationData)).

Keystore State

Keystore Read-Write State

The read-write state consists of the following mappings, which are indexed by keystore address. They are committed to using a siloed Indexed Merkle tree.

state: mapping(keystoreAddress: bytes32 => (dataHash: bytes32, verificationDataHash: bytes32));
balances: mapping(keystoreAddress: bytes32 => balance: uint256);
nonces: mapping(keystoreAddress: bytes32 => nonce: uint256);

These mappings store the following data:

  • state[keystoreAddress] is defined to support counterfactual initialization, meaning:
    • If state[keystoreAddress] == (bytes32(0), bytes32(0)), then keystoreAddress has been counterfactually initialized, and if keystoreAddress == keccak256(salt, keccak256(initialData), keccak256(initialVerificationData)) for some salt, initialData, and initialVerificationData, then initialData and initialVerificationData are interpreted as the signing and verification data associated with keystoreAddress.
    • Otherwise, if state[keystoreAddress] = (dataHash, verificationDataHash) for dataHash = keccak256(data) and verificationDataHash = keccak256(abi.encodePacked(extraPvsHash, vkey)), then data and (extraPvsHash, vkey) are the signing data and update verification key associated with keystoreAddress.
  • balances[keystoreAddress] is the ETH balance in wei associated with keystoreAddress.
  • nonces[keystoreAddress] is the nonce associated with keystoreAddress, defined to be the number of transactions previously initiated from keystoreAddress.

To authenticate a (dataHash, verificationDataHash) pair for a keystore account, we use the following data structure:

struct KeystoreAccount {
    bytes32 keystoreAddress;
    bytes32 salt;
    bytes32 dataHash;
    bytes verificationData;
}

The authentication of KeystoreAccount against a keystore state is given by the following function:

function authenticateKeystoreAccount(KeystoreAccount acct) {
    if (state[acct.keystoreAddress] != (bytes32(0), bytes32(0))) {
        require(state[acct.keystoreAddress] == (acct.dataHash, keccak256(acct.verificationData)));
        require(acct.salt == bytes32(0));
    } else {
        require(acct.keystoreAddress == keccak256(acct.salt, acct.dataHash, keccak256(acct.verificationData)));
    }
}

Note: Although the keystore state contains dataHash and verificationDataHash instead of data and verificationData, the preimages of dataHash and verificationDataHash will have appeared in rollup DA for accounts which have transacted on the keystore. Keystore nodes are expected to store these preimages and enable users to retrieve them via a JSON-RPC API.

Keystore Withdrawals State

The write-only withdrawals state is given by the following mapping, which is also committed to using a siloed Indexed Merkle tree:

withdrawals: mapping(withdrawalHash: bytes32 => withdrawal: Withdrawal);

for a Withdrawal represented by

struct Withdrawal {
    address to;
    uint256 amt;
}

and withdrawalHash = keccak256(abi.encodePacked(keystoreAddress, nonce)), where keystoreAddress is the keystore address of the user initiating the withdrawal and nonce is the nonce of the withdrawal transaction.