---
# System prepended metadata

title: Private message sharing for ETH2 validators implementation draft

---

# Private message sharing for ETH2 validators implementation draft


### Application **variables:**

- `rln_identity_commitment` - Identity commitment of the ETH2 validator, derived from `rln_secret_key`
- `rln_secret_key` - Secret key of the ETH2 validator, generated specifically for the purpose of joining the private messaging channel. Generated using the [Poseidon hash function](https://eprint.iacr.org/2019/458.pdf) (not SHA256)
- `validator_public_key` - BLS public key of the ETH2 validator, computed from `validator_private_key`
- `validator_private_key` - BLS private key of the ETH2 validator, which is used for signing consensus related transactions for ETH2
- `bls_signature` - a signature generated by the `validator_private_key` of the ETH2 validator for the `rln_identity_commitment` (the signed message is the `rln_identity_commitment` )

### **Smart contract registry implementation**

```solidity=
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.9;

import "./IRegistryContract.sol";

/**
 * @title ETH2 Private messaging registry contract
 * @notice The registry contract used by ETH2 validators to register in the private chat
 */
contract RegistryContract is IRegistryContract {
    /**
     * @notice Record the registration related parameters in the blockchain's logs and emit Registration event
     * @param pubkey A BLS12-381 public key of the ETH2 validator
     * @param idCommitment An identity commitment for the ETH2 validator for group membership
     * @param signature A BLS12-381 signature of the `idCommitment` signed by the ETH2 validator's private
     * key from which the `pubkey` is derived from
     */
    function register(
        bytes calldata pubkey,
        bytes calldata idCommitment,
        bytes calldata signature
    ) external override {
        require(pubkey.length == 48, "RegistryContract: invalid pubkey length");
        require(idCommitment.length == 32, "RegistryContract: invalid idCommitment length");
        require(signature.length == 96, "RegistryContract: invalid signature length");

        // Emit a registration event - the validity of the event to be processed offchain
        emit RegistrationEvent(pubkey, idCommitment, signature);
    }
}
```

### p2p protocol implementation using gossipsub-rln

The p2p nodes should implement the gossipsub-rln specification. Additionally they must implement additional data structures and logic as described in this section.

**Data structures**

- **`ValidatorStatus`** - enum having 3 states: `NOT_REGISTERED`, `REGISTERED` and `BANNED`, which represents the participation status in the messaging channel of the `validator_public_key` for a specific validator.
- **`membership_tree`** - (see gossipsub-rln implementation details)
- **`msg_identity_metadata`** - (see gossipsub-rln implementation details)
- **`rln_to_validator_key_mapping`** - local data structure, implemented as dictionary which maps the `rln_identity_commitment` to `validator_public_key` for the registered validators. It is mutated when a new validator is added to or removed from the **`membership_tree`** upon membership registration or membership removal.
- **`validator_pubkey_status_mapping`** - local data structure, implemented as dictionary which maps the `validator_public_key` to a **`ValidatorStatus`** enum value. It is mutated when a validator is added to or removed from the **`membership_tree`** upon membership registration or membership removal.

**Pubsub topics**

These can be changed, depending on the further application specific use cases, we should start with one topic:

- `rln_message` - the main pubsub topic to which the interested active validators should subscribe to for receiving RLN messages. The validators that want to publish messages must publish them to this topic.

**Message receiving and publishing**

The structure of the messages and the receiving and publishing rules should stay the same as in the gossipsub-rln specification.

### Rest API implementation

In order for the later joining peers to be able to reconstruct their **`membership_tree`** correctly, the active network peers (i.e. the active eth2 validators) will need to provide an additional request-response service such as REST API with a single endpoint:

`GET /api/v1/getSlashedMembers` 

which will return a list of `rln_secret_key` for the removed members from their **`membership_tree`**. The later joining participants will be able to reconstruct their local **`membership_tree`** by monitoring the smart contract for member registration and requesting information for the slashed members from the REST API provided from the other network participants.  The data returned from the REST endpoint can be obtained by parsing the **`validator_pubkey_status_mapping`** mapping, although for performance reasons a separate data structure might be used just for storing the rln secret keys of the banned users.

### Interactions description

**Membership registration**

Registration for the private messaging channel (that is the RLN membership contract for the application) will require additional requirements. We need to use separate credentials for validator membership, that is an identity commitment and a secret key which are different from the private and public key used by the validator for validating the beacon chain. The reason for this is to protect the validator for being compromised on the eth2 chain, because if we use the same credentials then their private key will be revealed if they are caught spamming on the private messaging channel and we don't want the validators to incur consequences outside of the private messaging channel itself. We need to use separate credentials, but we need to ensure that the entity that tries to register in the RLN membership contract is an active validator for the beacon chain. Upon registration the validators will need to sign their `rln_identity_commitment` with their `validator_private_key` (the one used for validating the beacon chain) and send the `bls_signature`, `validator_public_key` and `rln_identity_commitment` as calldata inputs to the specific register function in the smart contract. 

The smart contract register function will not execute any logic, but the inputs will be stored in the blockchain's logs. The peers active in the p2p network will monitor the blockchain's logs state and pick up the sent parameters. They will validate them by:

- validating that the `bls_signature` is correct for the `rln_identity_commitment` and
- validating that the `validator_public_key` is an active eth2 validator (their eth2 client can be queried or another external eth2 node)
- validating the `validator_public_key` is not already registered or banned

and if they're valid, they will add the `rln_identity_commitment` of the validator in their local **`membership_tree`** and modify their other local data structures: **`rln_to_validator_key_mapping`** and **`validator_pubkey_status_mapping`** accordingly.

**Membership removal**

When the validators are caught spamming their RLN secret key will be revealed and the peers will be able to remove the validator from their local **`membership_tree`** and  modify their other local data structures: 

- **`validator_pubkey_status_mapping`** by changing the value of the entry associated with `validator_public_key` to `ValidatorStatus.BANNED`.
- **`rln_to_validator_key_mapping`** by removing the entry associated with `rln_identity_commitment` from the mapping
