Report lead: @aragirtas
Today, we publish a second report from the Obol and Nethermind Research collaboration. This time, we cover another important topic â€“ key refreshing. Key refreshing allows the operators in a DV cluster to update their partial secret keys, while preserving the validatorâ€™s secret and public keys. We propose to use a Groth16 proof composition method (see below). An aggregator (one of the operators) generates a succinct wrapper SNARK that attests to the validity of a fair key refresh, and submits a commitment to the proof of a fair key refresh to a smart contract. If there are no whistleblower complaints about the proof for some time, the cluster starts using the fresh keys. If a whistleblower sends a fraud proof (see below) to the smart contract regarding what the aggregator submitted, the smart contract verifies the fraud proof and approves or declines the key refresh.
Resharing is a process that involves the redistribution or reassignment of cryptographic keys, secret shares, or other sensitive cryptographic materials in a manner that maintains the security and integrity of the cryptographic system. This concept is particularly relevant in scenarios where the distribution of cryptographic secrets needs to be modified among various parties or entities.
We are interested in resharing because of two reasons. Firstly, the operators in a cluster may change over time. Hence, we need to enable the current operators to provide partial keys to the incoming operators. This allows for smooth cluster transitions and continuity in the validation process. Secondly, resharing is valuable for proactive security measures. Operators in a cluster may periodically refresh their partial keys to prevent the gradual accumulation of (potentially) leaked partial keys over time.
Problem statement
Propose a key refresh scheme that allows operators within DV clusters to update their partial keys regularly. This approach should be publicly verifiable, and it should ensure that even in cases of collusion among excluded operators, they cannot reconstruct the validatorsâ€™ secret keys.
Full resharing keeping the public key (FRKP)
In the this section, we describe the full resharing keeping the public key (FRKP) method, which keeps the public key while renewing the shares of all participants by reexecuting the DKG process with minor modifications. After describing the method, we will give an example of a cluster performing a DKG and then a resharing.
Starting point. What do we have?
Assume we have a DV cluster with n operators. Each operator obtains a partial secret key participating in a DKG using a (t, n) verifiable secretsharing scheme. The partial secret keys are sk_1, \dots, sk_n, which are the (t,n) Shamir secret sharing of the secret sk.
What do we want to have?
Assume we wish to have a cluster with (t',n') structure, where operators have fresh partial secret keys sk'_1, \dots, sk'_{n'} of the same DV secret key sk. (keeping the DVâ€™s public key the same)
Throughout this report, we will call the operators that are still active and hold a partial secret key from the previous key refresh (or initial DKG) old operators.
How?
We employ the FRKP method, which we describe as follows. It is similar to DKG, but unlike DKG, in the FRKP method, only the old operators generates subshares, with a crucial difference that the shared secrets are their existing partial secret keys.
 Each old operator O_i creates (t', n') subshares of its current partial key sk_i,
 O_i randomly chooses a secret polynomial f_i(X) of degree t'1 over \mathbb{F}_q, where f_i(0)=sk_i.
 distributes the subshares s_{i,j}=f_i(j) to the corresponding operators O_j for j\in\{1,\dots,n'\}.
 When the operator O_j receives subshares from at least t old operators, it obtains its fresh partial secret key sk'_j by interpolating t subshares it received, i.e., sk_j'=\sum_{i\in \mathcal{S}} \lambda_{i}s_{i,j}, where \lambda_i is the appropriate Lagrange coefficient with respect to the old operator O_i and \mathcal{S} is a set of at least t old operators.
Remark. Notice that the fresh partial secret keys sk'_1, \dots, sk'_{n'} are (t',n') Shamir secret sharing of the same secret sk. Also, note that the fresh partial secret keys (sk'_1, \dots, sk'_{n'}) cannot be combined with old partial secret keys (sk_1, \dots, sk_n) to reconstruct the secret key sk of the DV.
Below, we give an example to show how operators in a cluster perform a DKG, obtain their partial secret keys and how they can refresh their partial secret keys, keeping the public key the same in the case that cluster mutates.
Example.
In the following example (see the figure below), we have a cluster with structure (3,4), meaning that there are 4 operators in the cluster, and the threshold is 3. Each operator participates in a DKG protocol and obtains its partial secret key. Then, the 3rd operator is exited (or excluded) from the cluster. The cluster decides to transition to a (4,5) structure and adds two new operators, i.e., operators 3 and 5. The old operators 1, 2, and 4 share their existing partial secret keys using a (4,5)secret sharing scheme. Upon receiving those subshares, all operators compute their fresh partial secret keys using the received subshares.
Challenges
Challenge 1. Accumulation of the shares of excluded operators
A potential threat may arise when an excluded operator or an external party collects the partial keys of operators who are not part of the cluster anymore (and have nothing at stake). Also, malicious operators in the cluster may collude with the previously exited (or excluded) operators. We need a mechanism to avoid this potential threat.
Solution to Challenge 1
Recall that there can be at most f_i < \frac{n_i}{3} malicious operators in a cluster, and the threshold should satisfy t_i\geq\frac{2n_i}{3}, where n_i is the number of operators in the cluster state S_i.
To avoid the partial keys accumulated by a possible malicious party, we cannot allow more than t_if_i 1 operators from the same cluster state S_i to leave. In other words, it should not be possible for the (t_if_i)th operator from S_i to leave, or for the cluster to exclude it. Instead, the cluster should initiate the withdrawal process to exit the validators that the cluster runs. Indeed, suppose we let the (t_if_i)th operator exit. In that case, it may be possible for f_i malicious and active operators from S_i to collude with (t_if_i) excluded operators from S_i. They can reconstruct the validatorsâ€™ secret key because the number of colluding operators from S_i will be t_if_i + f_i = t_i, which is the threshold of the cluster state S_i.
For example, assume that the initial state of a cluster consists of 4 operators (as in the figure below) with threshold 3. By assumption, there is only one malicious operator, say operator 1 (red). Suppose that the cluster state S_1 mutates by excluding operator 4 (green) and adding new operators (blue) 4, 5, and 6. Letâ€™s assume that the threshold for S_2 is t_2=4. Suppose, after a while, the second cluster state S_2 mutates again by excluding operator 3 (green) and adding a new operator 3 (grey) instead. The number of operators and the threshold in the current state S_3 stays the same, 6 and 4 respectively.
Notice that the excluded operators 3 (green) and 4 (green) from state S_1 can collude with the active and malicious operator 1 (red), also from state S_1. These colluding operators have 3 partial secret keys from S_1 in total, and this suffices to reconstruct the validatorsâ€™ secret keys because the threshold in S_1 was 3.
Notice that these colluding operators may seem harmless if we only check the current cluster state S_3 or the previous one because the threshold in these states is 4.
Therefore, after each key refresh, all old operators must delete their old partial secret keys. Moreover, before the operators in the cluster exclude an operator, they must guarantee that the number of excluded operators in any cluster state S_i is at most (t_if_i1) for all i.
Challenge 2. DoS attacks
Given that the distributed validator clusters are relatively small, in a synchronous protocol, a malicious actor can disrupt the operators and prevent them from carrying out their validator duties through a Denial of Service (DoS) attack. We need a design to mitigate the feasibility of DoS attacks.
Solution to Challenge 2
Since the size of the clusters is not too big, a malicious party can DoS the operators and disable them to perform validation duties if we assume synchronous communication model. The asynchronous communication model solves this problem. We could use asynchronous proactive secretsharing schemes for key refresh. However, in that case public verifiability cannot be achieved.
On the other hand, since we need a periodical key refresh, we still need a timebound after which the fresh partial keys will be used. Therefore, we propose to set the time bounds large enough to make DoS very costly, and small enough to guarantee proactive security.
Challenge 3. Public verifiability vs onchain costs
To ensure the transparency of resharing transactions accessible to the public, we want public verifiability of the refreshing procedure. At the same time, we should minimize the gas cost.
Solution to Challenge 3
Each operator generates a Groth16 proof composition, verifying a proof that attests to the validity of multiple honest resharing, each corresponding to a different validator and different versions of cluster_lock
and validator_keystore
files. Then, the operators exchange those Groth16 proof compositions.
After generating its fresh partial secret keys and fresh partial public keys, the aggregator generates another Groth16 proof to prove that the fresh partial public keys are computed correctly. Finally, the aggregator verifies all these proofs in a wrapper circuit and obtains a single Groth16 proof.
The aggregator submits only one proof with a set of public data to the smart contract. We follow an optimistic approach in which the smart contract does not verify the wrapper proof. It only stores a commitment to the wrapper proof and the corresponding public data. The smart contract makes computations only if a whistleblower claims that the wrapper proof is invalid. This keeps the onchain cost low. (See the gas estimation below).
Proposed solution
Computing the dealings
Each old operator generates subshares and resharing dealings as described in the Publicly Verifiable Secret Sharing proposal. To make the shares publicly verifiable, we follow the same idea of using SNARKs. Although the generation of the proofs is very similar, some crucial points need to be emphasized:
 In the key refresh, only the old operators generate subshares and the corresponding proofs.
 The constant terms of the secret polynomials of the old operators have to be their existing partial secret keys.
 The size of the public data that will be published is linear in the threshold t, unlike the PVSSbased DKG.
The detailed description of the curves and the proofs are given in Appendices CF below.
Next, we introduce our construction.
The construction
In this section, we present our construction, which mainly follows our Publicly Verifiable Secret Sharing proposal. Each old operator computes the subshares and a resharing dealing (including commitments to the secret polynomials, proofs, and some public data) using a Groth16 proof composition and exchanges it with other operators. After verifying the resharing dealings, each operator participates in a consensus for determining the set of t resharing dealings. Then, each operator computes its fresh partial secret keys and all fresh partial public keys locally.
After generating their fresh partial secret keys, the operators jointly generate cluster_lock
and validator_keystore
files. (Or multiple versions of these files if the cluster agrees to do so)
Then, an aggregator (ideally the leader of the cluster) generates another SNARK to prove that the fresh partial public keys are computed correctly. The aggregator generates a wrapper proof that attests to the validity of all proofs. The resulting wrapper proof and the corresponding public data are submitted to the smart contract using a Blob transaction as described in the EIP4844.
If no whistleblower raises a complaint about the validity of the wrapper proof, the operators participate in a consensus to determine when to use the fresh partial secret keys. Otherwise, if a whistleblower submits valid fraud proof (see below), the key refresh protocol is labeled as failed by the smart contract.
Assumptions and setup
Let S_{i} be a state of a cluster with n operators that run k validators with a threshold t. We will perform a key refresh for a transition to the new state S_{i+1} with n' operators that run k validators with a threshold t'. As a result, the operators in the new cluster state will obtain v verisons of cluster_lock
and validator_keystore
files.
We deploy a Key Manager Contract (KMC), which
 keeps a â€śto be excludedâ€ť list, which is initially empty,
 keeps the status of the resharing with \text{ResharingStatus} which is initially set to \text{Null} and can take two states during a key refresh: \text{failed}, \text{success},
 keeps the \text{EndAccusation}, which is the block height that shows the end of accusation period,
 stores Com_{\text{w}}, i.e., the versioned hash of the key refresh data that is included in the Blob transaction,
 accepts bond from whistleblowers,
 verifies fraud proofs provided by a whistleblower.
We assume the EIP4844: Shard Blob Transactions.
We assume operators agree on a way that they update the clusterdefinition
.
We assume that operators have a withdrawal process, and we leave it out of scope.
We assume a secure and authenticated communication channel.
We denote the number of operators, the threshold, and the maximum number of malicious operators in the state S_c as n_c,t_c, and f_c, respectively. Note that there can be at most f_c < \frac{n_c}{3} malicious operators in a cluster, and the threshold should satisfy t_c\geq\frac{2n_c}{3}, where n_i is the number of operators in the cluster state S_c.
Each operator maintains the list of excluded operators, i.e., \textrm{ExcludedOperators}, and the list of the number of excluded operators that participated in each cluster state, i.e., \textrm{NumberOfExOps}, in their Charon clients locally.
Subprocedure for checking the number of excluded operators
Each operator in a cluster state maintains a list of excluded operators for all cluster states in its Charon clients and checks the number of excluded operators before excluding an operator. More precisely, the operators maintains two lists, i.e.,
 a list \textrm{ExcludedOperators} of tuples (j, \textrm{Start}_j, \textrm{End}_j) for the excluded operators, where j denotes the excluded operator $O_j$â€™s id, \textrm{Start}_j and \textrm{End}_j denote the first, and the last cluster states that the operator O_j participated in, and
 a list \textrm{NumberOfExOps} of the values \textrm{NumEx}_i (initially zero), i.e., number of excluded operators which were active during the state S_i.
Using these list, operators count the number of operators excluded from the cluster states. The logic is as follows. Let N be the index of the current cluster state S_N. Before excluding an operator, e.g., O_j, each operator proceeds as follows.
\textrm{CheckNumExOps}(O_j):
 Append (j, \textrm{Start}_j, \textrm{End}_j) to the list \textrm{ExcludedOperators}.
 FOR i=0 TO N DO:
 IF \textrm{Start}_j \leq i \leq \textrm{End}_j

\textrm{NumEx}_i = \textrm{NumEx}_i+1

IF \textrm{NumEx}_i \geq t_if_i
RETURN (i, \textrm{NumEx}_i) 
END IF

 END IF
 IF \textrm{Start}_j \leq i \leq \textrm{End}_j
 END FOR
 RETURN â€ťSafeâ€ť
When the cluster is about to decide to exclude an operator or an operator wants to exit, each operator in the current cluster state performs the above check. If the logic returns (i, \textrm{NumEx}_i) for some i\leq N, the cluster withdraws the validators it runs. Otherwise, the cluster can exclude the operator. Below, we define this subprocedure that we are going to use in our key refresh scheme construction.
\textrm{check\_number\_of\_exited\_operators}\ (O_j)
 If \textrm{CheckNumExOps}(O_j) = (i, \textrm{NumEx}_i) for some i\leq N, the operators proceed with the withdrawal process.
 If \textrm{CheckNumExOps}(O_j) = \text{Safe}, the operators update the cluster by excluding the old operator O_j and adding new operators instead.
 The operators restart from step 1 of the key refresh.
Key refresh scheme

Each old operator checks whether the current
clusterdefinition
has at least n_c(t_cf_c1) node operators from the state S_c for all c. If not, they proceed with the withdrawal process to exit the validators that are being run by the cluster. 
Key refresh protocol starts with generating the subshares and proofs. Each old operator O_i computes the resharing dealing RD_{i}, which includes
 an inner Groth16 proof \pi_{\text{in}}^i for proving the correct subshare generation,
 an outer Groth16 proof \pi_{\text{out}}^i that attests to the validity of inner Groth16 proof \pi_{\text{in}}^i and correct computation of commitments to the secret polynomials,
 the commitments to the secret polynomial of the old operator O_i, i.e., \text{PCOM}_i,
as described in Appendix D.

Each old operator O_i sends subshare s_{\ell}^{i,j,b}\in \mathbb{F}_r for $\ell=1, \dots, nâ€™$$z = 1, \dots, n$$j=1, \dots, k$ and b=1, \dots, v, to operator O_j, along with its resharing dealing RD_i and a signature \sigma_i on the resharing dealing RD_i within a time window \tau_D.
\tau_D is a reasonable time bound for operators to send the subshares, dealings, and signatures to each other.

If an operator has not received subshares from the old operator O_j, it publishes a complaint among other operators in the cluster that it couldnâ€™t receive subshares from O_j.
 If at least t complaints about O_j are published within a time window \tau_D, the operators run the subprocedure on input O_j, i.e., \textrm{check\_number\_of\_exited\_operators}\ (O_j).

If an operator has not received (RD_j,\sigma_j), it asks other operators to send (RD_j,\sigma_j) within a time window \tau_D.
 If nobody has the (RD_j,\sigma_j), the operators run the subprocedure on input O_j, i.e., \textrm{check\_number\_of\_exited\_operators}\ (O_j).

Upon receiving the subshares, the resharing dealings RD_j, and the signatures \sigma_j from the old operators O_j, the operator O_i checks the signatures, resharing dealings and subshares as follows.
 Each operator O_i verifies the signature of each old operator O_j
 if a signature \sigma_j is invalid, the O_i notifies the operator O_j to send a valid signature in time \tau_D.
 If the old operator O_j does not send a valid signature within a time window \tau_D, O_i asks other operators to send the valid signature \sigma_j of the operator O_j within a time window \tau_D (if they have it).
 If nobody has a valid signature from O_j, the operators run the subprocedure on input O_j, i.e., \textrm{check\_number\_of\_exited\_operators}\ (O_j).
 If the old operator O_j does not send a valid signature within a time window \tau_D, O_i asks other operators to send the valid signature \sigma_j of the operator O_j within a time window \tau_D (if they have it).
 if a signature \sigma_j is invalid, the O_i notifies the operator O_j to send a valid signature in time \tau_D.
 Each operator O_i verifies the subshares that come from O_j, and the proofs in the resharing dealing RD_j
 If any subshare or proof is invalid, O_i publishes a complaint about the invalid subshare or dealing. O_i publishes the proofs and the subshares that came from O_j along with its signature \sigma_j.
 If the complaint is valid, the operators run the subprocedure on input O_j, i.e., \textrm{check\_number\_of\_exited\_operators}\ (O_j).
 If the complaint is invalid, the operators run the subprocedure on input O_i, i.e., \textrm{check\_number\_of\_exited\_operators}\ (O_i).
 If any subshare or proof is invalid, O_i publishes a complaint about the invalid subshare or dealing. O_i publishes the proofs and the subshares that came from O_j along with its signature \sigma_j.
 Each operator O_i verifies the signature of each old operator O_j

Operators participate in a consensus on t valid resharing dealings, i.e., \mathcal{S}:= \{RD_{i_1}, \dots, RD_{i_t}\} that they received.

After reaching consensus on the set \mathcal{S}, each operator O_i

computes its fresh partial secret keys by performing Lagrange interpolation with the subshares that came from the owners of the resharing dealings in the set \mathcal{S}, i.e., s_i^{z,j,b} \in \mathbb{F}_r for $z \in \mathcal{S}$$z = 1, \dots, n$$j=1, \dots, k$, and b=1, \dots, v.
The fresh partial signing key sk_{i}'^{j,b} of the operator O_i for the validator j for the cluster version b is computed as sk_{i}'^{j,b}= \sum\limits_{z\in \mathcal{S}} \lambda_z s_i^{z,j,b} for j=1, \dots, k and b=1, \dots, v.

obtains the partial public key of the operator O_s, i.e., pk_s'^{j,b}\in \mathbb{G}_1^{\text{in}}, for the validator j for the cluster version b by computing pk_s'^{j,b} = \sum\limits_{z \in \mathcal{S}}^{} \lambda_z\cdot \left(\sum\limits_{\ell=0}^{t'1} {s^{\ell}}\cdot A_{\ell}^{z,j,b}\right) for $s=1, \dots, nâ€™$$z = 1, \dots, n$$j=1, \dots, k$, and b=1,\dots,v, where $A_{\ell}^{z,j,b}$â€™s are the commitments to the coefficients of the secret polynomials.
Note that the validatorsâ€™ public keys, i.e., PK_{validator}:=\{pk^1, \dots, pk^k \in \mathbb{G}^{\text{in}}_1\} stay the same.

outputs
 fresh
cluster_lock_b
for b=1, \dots, v.  fresh
validator_keystore_b
for b=1, \dots, v.
We leave the creation of the above output files out of scope. They are generated as in DKG. Note that the Charon clients generate the fresh
cluster_lock
file with a joint effort, as the file includes the BLS aggregate signature of the operators.  fresh


The aggregator generates a SNARK, i.e., \pi_{\text{pk}}, that proves the correct computation of the fresh partial secret keys, as described in Appendix E.

The aggregator generates the wrapper proof and obtains \pi_{\text{w}}, the commitments Pub_{\text{w}} and Pub_{\text{pk}}, and a set of public data PD, as described in Appendix F].

The aggregator submits the key refresh data, i.e., (\pi_{\text{w}}, Pub_{\text{w}}, Pub_{\text{pk}}, PD), as blob data (as described in EIP4844) to the KMC within a time window \tau_D.

If the aggregator does not submit the key refresh data within a time window \tau_D, the operators run the subprocedure on input â€śaggregatorâ€ť, i.e., \textrm{check\_number\_of\_exited\_operators}\ (\text{aggregator}).

Upon receiving the key refresh data, i.e., (\pi_{\text{w}}, Pub_{\text{w}}, Pub_{\text{pk}}, PD), the KMC
 stores the versioned hash of (\pi_{\text{w}}, Pub_{\text{w}}, Pub_{\text{pk}}, PD), i.e., Com_{\text{w}},
 sets \text{EndAccusation} to current\_slot + \tau_w.
\tau_w is the time window for a whistleblower to generate and send the fraud proof. It may be the same as the blob data duration.

Any whistleblower can check whether the wrapper proof is valid.

If the proof is invalid, a whistleblower submits a fraud proof to the KMC along with a small bond B within a time window \tau_w.
$B$ is a small bond to avoid malicious parties to send irrelevant data.

Upon receiving the fraud proof, the KMC verifies it.
 If there is no bond B, the KMC rejects the fraud proof.
 If the fraud proof is valid, the KMC

adds the aggregator to the â€śto be excludedâ€ť list, which is initially empty.

sets \text{ResharingStatus}: \text{failed}.

rewards the whistleblower.
We leave how to reward a whistleblower as a todo. It may possibly be rewarded by calling a function of another contract (using leftover rewards).

pays back the bond B to the whistleblower.

 If the fraud proof is invalid, the KMC
 slashes the bond of the whistleblower,
 sets \text{ResharingStatus}: \text{success}

If no whistleblower triggers the KMC within a time window \tau_w, any operator triggers the KMC. When triggered, the KMC sets the \text{ResharingStatus}: \text{success} if current\_slot > \text{EndAccusation}.

Operators check the \text{ResharingStatus} of the KMC.
 If the operators see that \text{ResharingStatus}: \text{failed}, the operators run the subprocedure on input â€śaggregatorâ€ť, i.e., \textrm{check\_number\_of\_exited\_operators}(\text{aggregator}).
 If the operators see that \text{ResharingStatus}: \text{success}, they participate in a consensus protocol to decide when to use the fresh keys regarding each version of the
cluster_lock
andvalidator_keystore
files. The result of the consensus is \tau_b for b=1,\dots,v.

After the last duty before each \tau_b, for b=1,\dots,v, each operator
 deletes the
cluster_lock_b1
file from its Charon client.  loads the
cluster_lock_b
file to its Charon client.  deletes the
validator_keystore_b1
from its validator client  loads the
validator_keystore_b
to its validator client
 deletes the
Remark. In the case of b>1, the operators should keep the unused versions of the validator_keystore
file in a secure (physically separated) storage. The operators should delete their old keys from their validator clients and keep only those for the current period in their validator clients. Note that deleting the old partial secret keys is crucial because of a potential accumulation of the old partial secret keys from the same cluster state. Please see the â€śSolution to Challenge 1â€ť above for a detailed explanation of this potential threat.
Next, we describe how a whistleblower generates a fraud proof.
Computing the fraud proof
When a whistleblower finds an invalid key refresh data, i.e., (\pi_{\text{w}}, Pub_{\text{w}}, Pub_{\text{pk}}, PD), in the Blob Tx, it generates a fraud proof. The types of complaints that a whistleblower can raise are as follows.
 Type 1 claims that Pub_{\text{w}} \neq H_2(PD)
 Type 2 claims that Pub_{\text{pk}} \neq H_1(PK_{validator})
 Type 3 claims that \textrm{Groth16.Verifier}(R_{\text{w}}, \texttt{vk}_{\text{w}}, (Pub_{\text{w}}, Pub_{\text{pk}}), \pi_{\text{w}})=0
How does KMC verify the fraud proof?
When the KMC receives the fraud proof,
 If the complaint is valid return valid,
 If the complaint is not valid return invalid.
Notice that the complaint that will be verified by the KMC may be one of the three types above. The whistleblower calls one of the functions in the KMC, according to the type of complaint. These functions are as follows.
Note that Com_{\text{w}} denotes the commitment to the key refresh data, i.e., (\pi_{\text{w}}, Pub_{\text{w}}, Pub_{\text{pk}}, PD), that is stored in the storage of the KMC when the Blob Tx is received, and VH() denotes the versioned hash as described in EIP4844.
 verify_complaint_public_data: It takes (\pi_{\text{w}}, Pub_{\text{w}}, Pub_{\text{pk}}, PD) as input, and outputs valid or invalid.
 It checks
 whether Com_{\text{w}} = VH(\pi_{\text{w}}, Pub_{\text{w}}, Pub_{\text{pk}}, PD) and
 whether Pub_{\text{w}} =H_2(PD)
 If this is not the case, return valid.
 Otherwise, return invalid.
 It checks
 verify_complaint_public_keys: It takes (\pi_{\text{w}}, Pub_{\text{w}}, Pub_{\text{pk}}, PD) as input, and outputs valid or invalid.
 It checks
 whether Com_{\text{w}} = VH(\pi_{\text{w}}, Pub_{\text{w}}, Pub_{\text{pk}}, PD) and
 whether the received Pub_{\text{pk}} is identical to the Pub_{\text{pk}} stored in the storage of KMC during the DKG.
 If this is not the case, return valid.
 Otherwise, return invalid.
 It checks
 verify_complaint_wrapper_proof: It takes (\pi_{\text{w}}, Pub_{\text{w}}, Pub_{\text{pk}}, PD) as input, and outputs valid or invalid.
 It checks
 whether Com_{\text{w}} = VH(\pi_{\text{w}}, Pub_{\text{w}}, Pub_{\text{pk}}, PD)
 whether \textrm{Groth16.Verifier}(R_{\text{w}}, \texttt{vk}_{\text{w}}, (Pub_{\text{w}}, Pub_{\text{pk}}), \pi_{\text{w}}) = 1, where R_{\text{w}} and \texttt{vk}_{\text{w}} are the relation and verification key for the wrapper circuit.
 If this is not the case, return valid.
 Otherwise, return invalid.
 It checks
Gas estimation
Disclaimer. We did gas cost estimation according to the known gas costs for submitting calldata. However, the key refresh data is submitted as Blob data. Submitting blob data requires blob gas, which, currently, cannot be translated into USD. Note that the blob gas cost of submitting Blob data would be less than estimated in this section.
The table below gives a rough gas estimation for submitting the key refresh data, i.e., (\pi_{\text{w}}, Pub_{\text{w}}, Pub_{\text{pk}}, PD), and storing the versioned hash of the key refresh data, i.e., Com_{\text{w}}.
Data  # tuples  Size (bytes)  Example data size (in Bytes) (for n'=4, t=3, b=1)  Example data size (in Bytes) (for n'=4, t=3, b=10) 

PI  n'  n'  4  4 
Pub_{\text{in}}^i  t  32t  96  96 
Pub_{\text{out}}^i  t  48t  144  144 
\pi_{\text{in}}^i  t  192t  576  576 
\pi_{\text{out}}^i  t  288t  864  864 
\pi_{\text{pk}}  1  288  288  288 
Pub_{\text{pk}}  1  48  48  480 
Pub_{\text{com}}  1  48  48  480 
\text{LH}  b  32b  32  320 
\text{SA}  b  96b  96  960 
Pub_{\text{w}}  1  32  32  32 
\pi_{\text{w}}  1  128  128  128 
Com_{\text{w}}  1  32  32  32 
TOTAL bytes  n+ 560t + 128b + 576  2,388 bytes  3,540 bytes  
(16 gas per byte of calldata)  16n+8,960t + 2,048b + 9,216 gas  38,208 gas  56,640 gas  
Updating storage (Com_{\text{w}})  5,000 gas  5,000 gas  5,000 gas  
Tx cost  21,000 gas  21,000 gas  21,000 gas  
TOTAL gas cost (calldata + storage + Tx)  ~ 16n + 8,960t + 2,048b + 34,216 gas  ~ 64,208 gas (\approx 2.32 USD (assuming 20 gwei per gas)  ~ 82,640 gas (\approx 2.98 USD (assuming 20 gwei per gas) 
 PI has the indices, and we assumed each index can be represented by 1 byte,

Pub_{\text{in}}^i is an \mathbb{F}_r element, i.e., 255 bits = 32 bytes, (Note that r is 255bit prime, source)

Pub_{\text{out}}^i is an \mathbb{F}_q element, i.e., 381 bits = 48 bytes, (Note that q is 381bit prime, source)

\pi_{\text{in}}^i includes 2 elements from \mathbb{G}_1^{\text{in}} and 1 element from \mathbb{G}_2^{\text{in}}, i.e., 48+48+96 = 192 bytes, (Note that q is 381bit prime, source)

\pi_{\text{out}}^i includes 2 elements from \mathbb{G}_1^{\text{out}} and 1 element from \mathbb{G}_2^{\text{out}}, i.e., 96+96+96 = 288 bytes, (Note that p is 767bit prime, source)

\pi_{\text{pk}} includes 2 elements from \mathbb{G}_1^{\text{out}} and 1 element from \mathbb{G}_2^{\text{out}}, i.e., 96+96+96 = 288 bytes, (Note that p is 767bit prime, source)

Pub_{\text{pk}} and Pub_{\text{com}} are \mathbb{F}_q elements, i.e., 381 bits = 48 bytes, (Note that q is 381bit prime, source)

Pub_{\text{w}} is an \mathbb{F}_{\ell} element, i.e., 255 bits = 32 bytes, (Note that \ell is 255bit prime, source)

\text{LH} is the hash of the
cluster_lock
file which is 32 bytes. 
\text{SA} is an aggregate BLS signature, which is 96 bytes according to the Beacon chain spec.

\pi_{\text{w}} includes 2 elements from \mathbb{G}_1^{\text{w}} and 1 element from \mathbb{G}_2^{w}, i.e., 32+32+64 = 128 bytes, (Note that p is 255bit prime, source)

Com_{\text{w}} is a 256bit hash of a KZG commitment to the key refresh data, i.e., 32 bytes. (source)
Refreshing period
In the previous section we gave an estimation for submitting and storing the wrapper proof and the corresponding public data. Note that the cost that we computed needs to be paid every time the operators refreshes their partial keys. If a cluster decides to generate more than two versions of cluster_lock
and validator_keystore
files simultaneously, the refreshing period becomes less than 1 month if we fix the monthly cost as 1.5 USD per cluster.
All computations are done by assuming 1 gas = 20 gwei and 1 ETH = 1,800.00 USD.
Number of versions vs refreshing period
Structure  operators  threshold  versions  cost of key refresh  refreshing period  monthly cost per cluster 

(3,4)  4  3  1  2.275  1.517  1.5 
(3,4)  4  3  2  2.349  0.783  1.5 
(3,4)  4  3  3  2.423  0.538  1.5 
(3,4)  4  3  4  2.497  0.416  1.5 
(3,4)  4  3  5  2.57  0.343  1.5 
(3,4)  4  3  10  2.939  0.196  1.5 
(3,4)  4  3  20  3.676  0.123  1.5 
(3,4)  4  3  50  5.888  0.079  1.5 
(3,4)  4  3  100  9.575  0.064  1.5 
(7,10)  10  7  1  3.569  2.379  1.5 
(7,10)  10  7  2  3.643  1.214  1.5 
(7,10)  10  7  3  3.717  0.826  1.5 
(7,10)  10  7  4  3.79  0.632  1.5 
(7,10)  10  7  5  3.864  0.515  1.5 
(7,10)  10  7  10  4.233  0.282  1.5 
(7,10)  10  7  20  4.97  0.166  1.5 
(7,10)  10  7  50  7.182  0.096  1.5 
(7,10)  10  7  100  10.868  0.072  1.5 
Notice that the worst case occurs when a cluster generates a single version. To mitigate this, the cluster may run more than one validators.
In the below table, we fix the monthly cost as 1.5 USD per validator and we assume that cluster generates a single version of cluster_lock
and validator_keystore
files. The refresh period becomes less than 1 month if a cluster runs more then two validators.
Number of validators vs refreshing period
Structure  operators  threshold  validators  cost of key refresh  refreshing period  monthly cost per cluster 

(3,4)  4  3  1  2.275  1.516666666667  1.5 
(3,4)  4  3  2  2.275  0.758333333333  3 
(3,4)  4  3  3  2.275  0.505555555556  4.5 
(3,4)  4  3  4  2.275  0.379166666667  6 
(3,4)  4  3  5  2.275  0.303333333333  7.5 
(3,4)  4  3  10  2.275  0.151666666667  15 
(3,4)  4  3  20  2.275  0.075833333333  30 
(3,4)  4  3  50  2.275  0.030333333333  75 
(3,4)  4  3  100  2.275  0.015166666667  150 
(7,10)  10  7  1  3.569  2.379333333333  1.5 
(7,10)  10  7  2  3.569  1.189666666667  3 
(7,10)  10  7  3  3.569  0.793111111111  4.5 
(7,10)  10  7  4  3.569  0.594833333333  6 
(7,10)  10  7  5  3.569  0.475866666667  7.5 
(7,10)  10  7  10  3.569  0.237933333333  15 
(7,10)  10  7  20  3.569  0.118966666667  30 
(7,10)  10  7  50  3.569  0.047586666667  75 
(7,10)  10  7  100  3.569  0.023793333333  150 
We gave the possible key refresh periods, which cost a monthly 1.5 USD per validator in the above tables. If we want to reduce the cost further, we should either generate multiple versions or run multiple validators.
The worst case scenario is that a cluster runs a single validator and generates a single versions of the cluster_lock
and validator_keystore
files.
 For such a cluster of 4 operators, the refreshing period may be more than ~1,6 months to have a monthly cost of 1.5 USD.
 For such a cluster of 10 operators, the refreshing period may be more than ~2,4 months to have a monthly cost of 1.5 USD.
Todoâ€™s and open questions
 How do we compensate the aggregator for its extra work?
 How do we compensate the aggregatorâ€™s effort if the principal provider does not activate the validator?
 How should we reward the whistleblower?
References
 How to share a secret by Adi Shamir. 1979. Commun. ACM 22, 11 (Nov. 1979), 612â€“613. https://doi.org/10.1145/359168.359176
 A practical scheme for noninteractive verifiable secret sharing, by P. Feldman, 28th Annual Symposium on Foundations of Computer Science (sfcs 1987), Los Angeles, CA, USA, 1987, pp. 427438, doi: 10.1109/SFCS.1987.4.
 Proactive Secret Sharing Or: How to Cope With Perpetual Leakage by Herzberg, A., Jarecki, S., Krawczyk, H., Yung, M. (1995). In: Coppersmith, D. (eds) Advances in Cryptology â€” CRYPT0â€™ 95. CRYPTO 1995. Lecture Notes in Computer Science, vol 963. Springer, Berlin, Heidelberg. https://doi.org/10.1007/3540447504_27
 Secure Distributed Key Generation for DiscreteLog Based Cryptosystems by Rosario Gennaro, StanisĹ‚aw Jarecki, Hugo Krawczyk, and Tal Rabin, J. Stern (Ed.): EUROCRYPTâ€™99, LNCS 1592, pp. 295â€“310, 1999.
 Fast Multiparty Threshold ECDSA with Fast Trustless Setup by Rosario Gennaro and Steven Goldfeder, https://eprint.iacr.org/2019/114.pdf
 Noninteractive distributed key generation and key resharing by Groth, J. Cryptology ePrint Archive, Report 2021/339 (2021), https://eprint.iacr.org/2021/339
 Design and analysis of a distributed ECDSA signing service by Jens Groth and Victor Shoup. Cryptology ePrint Archive, Report 2022/506 (2022), https://eprint.iacr.org/2022/506
 How to share a secret by Adi Shamir. 1979. Commun. ACM 22, 11 (Nov. 1979), 612â€“613. https://doi.org/10.1145/359168.359176
 A practical scheme for noninteractive verifiable secret sharing, by P. Feldman, 28th Annual Symposium on Foundations of Computer Science (sfcs 1987), Los Angeles, CA, USA, 1987, pp. 427438, doi: 10.1109/SFCS.1987.4.
 On the Size of PairingBased Noninteractive Arguments, by Groth, J. (2016). In: Fischlin, M., Coron, JS. (eds) Advances in Cryptology â€“ EUROCRYPT 2016. EUROCRYPT 2016. Lecture Notes in Computer Science(), vol 9666. Springer, Berlin, Heidelberg. https://doi.org/10.1007/9783662498965_11
 Families of SNARKFriendly 2Chains of Elliptic Curves., by El Housni, Y., Guillevic, A. (2022). In: Dunkelman, O., Dziembowski, S. (eds) Advances in Cryptology â€“ EUROCRYPT 2022. EUROCRYPT 2022. Lecture Notes in Computer Science, vol 13276. Springer, Cham. https://doi.org/10.1007/9783031070853_13
 A deep dive into DKG, chain of SNARKs, and arkworks, by Nicolas Gailly (Cryptonet), 2022. (Protocol Labs Research)
 https://github.com/nikkolasg/arkdkg
 https://ethresear.ch/t/bw6overbls12381/10321
 https://ethereum.org/en/developers/docs/evm/opcodes/
 https://eips.ethereum.org/EIPS/eip196
 https://eips.ethereum.org/EIPS/eip197
 https://eips.ethereum.org/EIPS/eip1108
 https://hackmd.io/@benjaminion/bls12381
 https://hackmd.io/@gnark/bw6_bls12381
 https://github.com/yelhousni/gnarkcrypto
Appendices
A. Groth16 scheme
Let \mathbb{G}_1 and \mathbb{G}_2 be two cyclic additive subgroups with the same prime order. Let R be a binary relation. The Groth16 scheme is a noninteractive argument of knowledge which consists of four algorithms as follows:
 \textrm{Groth16.Setup}(1^{\lambda}, R)\to (\texttt{crs},\texttt{td}): The \textrm{Groth16.Setup} algorithm takes a security parameter \lambda and the relation R as inputs, and it outputs a common reference string \texttt{crs} and a simulation trapdoor \texttt{td}.
 \textrm{Groth16.Prover}(R, \texttt{crs}, u,w)\to \pi =(A,B,C): The \textrm{Groth16.Prover} algorithm takes the relation R, common reference string \texttt{crs}, statement u and witness w as inputs, and it outputs a proof \pi=(A,B,C), where A, C \in \mathbb{G}_1 and B \in \mathbb{G}_2.
 \textrm{Groth16.Verifier}(R, \texttt{vk}, u, \pi)\to 0/1: The \textrm{Groth16.Verifier} algorithm takes the relation description R, the verification key \texttt{vk} (a part of the \texttt{crs}), the statement u and the proof \pi as inputs, and it outputs 0/1 (â€śrejectâ€ť/â€śacceptâ€ť).
 \textrm{Groth16.Sim}(\texttt{td}, u)\to \pi_{sim}: The \textrm{Groth16.Sim} algorithm takes the trapdoor and the statement u as inputs, and it outputs a simulated proof \pi_{sim}.
B. BLS signature scheme
Let \mathbb{F}_r be the finite field with prime order r, and \mathbb{G}_1 and \mathbb{G}_2 be two additive cyclic groups with prime order r, and \mathbb{G}_t be a multiplicative target group with the same order. Let g_1,g_2 be generators of \mathbb{G}_1,\mathbb{G}_2, respectively. A bilinear pairing is a map e:\mathbb{G}_1 \times \mathbb{G}_2 \to \mathbb{G}_t linear in both entries, nondegenerate, and efficiently computable. Let H:\{0,1\}^* \to \mathbb{G}_2 be a hash function which maps any binary string to the group \mathbb{G}_2.
The BLS signature scheme consists of three algorithms: key generation, signature generation, and verification. These are as follows:

\textrm{BLS.KeyGen}(par)\to (sk,pk): The key generation algorithm takes the public parameters par as input and outputs the key pair as follows:
 chooses a uniformly random secret key, sk \xleftarrow{\$} \mathbb{F}_r
 computes the corresponding public key pk \gets sk \cdot g_1 (Note that pk \in \mathbb{G}_1)

\textrm{BLS.Signer}(M,sk)\to \sigma: Signature generation algorithm takes the message M and the secret key sk as inputs, and outputs the signature \sigma as follows:
 computes the hash h\in \mathbb{G}_2 of the message M, i.e., h \gets H(M)
 computes the signature \sigma\in \mathbb{G}_2 on the message M, i.e., \sigma \gets sk \cdot h.

\textrm{BLS.Verifier}(\sigma,M, pk)\to 1/0: Verification algorithm takes the message M, the signature \sigma and the public key pk as inputs, and outputs 1 (â€śacceptâ€ť) if e(pk,h)=e(g_1,\sigma), 0 (â€śrejectâ€ť) otherwise.
Note that BLS signatures and public keys can be aggregated, and the aggregated signature can be verified with the aggregated public key if the messages are the same. (BLS signatures on different messages can also be aggregated, but in this report, we are not interested in that case.) For instance, assume we have N signers P_1, \dots, P_N. Let pk_1, \dots, pk_N be their respective public keys. The verification of N signatures \sigma_1, \dots, \sigma_N on the same message M produced respectively by P_1, \dots, P_N is done by checking e(apk,H(M))=e(g_1,\sigma), where apk =\sum\limits_{i=1}^{N}pk_i is the aggregated public key, and \sigma =\sum\limits_{i=1}^{N}\sigma_i is the aggregated signature.
C. The curves
For the Groth16 proof composition, we use a 2chain of curves as described in [8] and this repo. More precisely, we use BLS12381 as the inner curve and BW6767 as the outer curve:

the BLS12381 curve is denoted as E_1(\mathbb{F}_q) whose scalar field is denoted as \mathbb{F}_r. The subgroups are denoted as \mathbb{G}_1^{\text{in}} and \mathbb{G}_2^{\text{in}}, and the generator of \mathbb{G}_i^{\text{in}} is denoted by G_i^{\text{in}}.
Note that we will use the generator G_1^{\text{in}} of \mathbb{G}_1^{\text{in}} for committing to the secret polynomials, and computing the public keys for the threshold BLS signature scheme as specified in Beacon chain spec.

the BW6767 curve is denoted as E_2(\mathbb{F}_p) whose scalar field is denoted as \mathbb{F}_q. The subgroups are denoted as \mathbb{G}_1^{\text{out}} and \mathbb{G}_2^{\text{out}}.
For the SNARK for the validity of the public keys, we also use E_2(\mathbb{F}_p).
For the wrapper SNARK, we use the alt_bn128 curve, which we denote as E_3(\mathbb{F}_{\ell}). The corresponding subgroups are denoted as \mathbb{G}_1^{\text{w}} and \mathbb{G}_2^{\text{w}}.
D. Groth16 proof composition
Each old operator O_i computes a Groth16 proof composition as follows.
Note that we are performing v key refreshes at the same time, to have v versions of the partial secret keys and cluster_lock
files. The superscript b denotes the version number of the variables used in the following constructions. Also note that if the cluster decides to generate only a single version, it is enough to set b=1.
Inner SNARK:
The inner circuit is over \mathbb{F}_r. The old operator O_i generates a proof \pi_{\text{in}}^i=(A_{\text{in}} ^i,B_{\text{in}} ^i,C_{\text{in}} ^i), where A_{\text{in}} ^i,C_{\text{in}} ^i\in \mathbb{G}_1^{\text{in}}, B_{\text{in}} ^i \in \mathbb{G}_2^{\text{in}}. We will use the hash H_0 : \{0,1\}^* \to \mathbb{F}_{r} for committing to the public data.
 Private inputs:

coefficients of the secret polynomials, i.e., (a_0^{i,j,b}, \dots, a_{t'_{}1}^{i,j,b}) \in \mathbb{F}_r^{kt'v} for j=1, \dots, k and b=1,\dots, v, which are chosen by the prover, where a_0^{i,j,b} = sk_i^j for all b=1, \dots, v.
This is the most crucial point of resharing: the constant term of the secret polynomials should be the existing partial secret key of the old operator for the corresponding validator.

subshares (s_1^{i,j,b}, \dots, s_{n'_{}}^{i,j,b}) \in \mathbb{F}_r^{kn'v} for j=1, \dots, k and b=1, \dots, v, which are computed by evaluations of the secret polynomials at the indices in the public inputs.

 Public inputs:
 indices of all operators (subshare holders), i.e., PI=\{1, \dots, n'\}
 Pub_{\text{in}}^i= H_0((a_0^{i,j,b}, \dots, a_{t'_{}1}^{i,j,b})_{j=1,\dots,k; \ b=1,\dots,v})
 Relation R_{\text{in}}:
 Assert s_{\ell}^{i,j,b} = \sum\limits_{z=0}^{t'_{}1}a_z^{i,j,b} \ell^z for \ell = 1, \dots, n'_{}, j=1, \dots, k and b=1,\dots,v.
 Assert that Pub_{\text{in}}^i= H_0((a_0^{i,j,b}, \dots, a_{t'_{}1}^{i,j,b})_{j=1,\dots,k; \ b=1,\dots,v})
Outer SNARK:
The outer circuit is over \mathbb{F}_q. The old operator O_i generates a proof \pi_{\text{out}}^i=(A_{\text{out}}^i,B_{\text{out}}^i,C_{\text{out}}^i), where A_{\text{out}}^i,C_{\text{out}}^i\in \mathbb{G}_1^{\text{out}}, B_{\text{out}}^i \in \mathbb{G}_2^{\text{out}}. We will use the hash H_1 : \{0,1\}^* \to \mathbb{F}_{q} for committing to the public data. We denote the relation for the inner proof as R_{\text{in}} and the verification key for the inner proof as \texttt{vk}_{\text{in}}.

Private inputs:

coefficients of the secret polynomials, i.e., (a_0^{i,j,b}, \dots, a_{t'_{}1}^{i,j,b})_{j=1, \dots, k; \ b=1,\dots, v} \in \mathbb{F}_r^{kt'v}.

commitments to coefficients of the secret polynomials, i.e., \text{PCOM}_i:=\{(A_0^{i,j,b}, \dots, A_{t'_{}1}^{i,j,b})_{j=1, \dots, k; \ b=1,\dots, v} \in {(\mathbb{G}_1^{\text{in}})}^{kt'v}\}, where A_{\ell}^{i,j,b} = a_{\ell}^{i,j,b}\cdot G_1^{\text{in}}.
According to the Beacon chain spec, the public key of the BLS signature scheme is specified as an element of \mathbb{G}_1^{\text{in}}. Since we will use the commitments to compute the public keys, we use the generator of \mathbb{G}_1^{\text{in}}, i.e., G_1^{\text{in}}, for committing to the secret polynomials.


Public inputs:
 indices of all operators (subshare holders), i.e., PI=\{1,\dots, n'\}
 Pub_{\text{in}}^i= H_0((a_0^{i,j,b}, \dots, a_{t'_{}1}^{i,j,b})_{j=1,\dots,k; \ b=1,\dots,v})
 the inner proof \pi_{\text{in}}^i=(A_{\text{in}}^i,B_{\text{in}}^i,C_{\text{in}}^i) (using the same coefficients of the secret polynomials and secret shares as above)
 Pub_{\text{out}}^i := H_1(\text{PCOM}_i)

Relation R_{\text{out}}:
 Assert Pub_{\text{in}}^i= H_0((a_0^{i,j,b}, \dots, a_{t'_{}1}^{i,j,b})_{j=1,\dots,k; \ b=1,\dots,v})
 Assert A_\ell^{i,j,b}=a_\ell^{i,j,b}\cdot G_1^{\text{in}} for \ell = 0, \dots, t'_{}1, j=1, \dots, k and b=1, \dots, v.
 Assert Pub_{\text{out}}^i := H_1(\text{PCOM}_i)
 Assert \textrm{Groth16.Verifier}(R_{\text{in}}, \texttt{vk}_{\text{in}},(PI,Pub_{\text{in}}^i), \pi_{\text{in}}^{i})=1.
Each old operator O_i obtains \pi^i_{\text{out}} and (PI, Pub_{\text{in}}^i,\pi_{\text{in}}^i, Pub_{\text{out}}^i).
E. The SNARK for proving the validity of the public keys
Only the old operators generate the Groth16 proof composition, as described in Appendix D, and send the proofs and other public data including (PI, \pi_{\text{in}}^i,Pub_{\text{in}}^i, Pub_{\text{out}}^i,\text{PCOM}_i) and the corresponding subshares to all operators in the cluster. All operators participate in a consensus protocol to agree on a set \mathcal{S} of t old operators with valid resharing dealings.
Upon agreeing on the set \mathcal{S}, each operator O_i verifies the proof \pi_{out}^z from the old operators O_z for z\in \mathcal{S}.

The operator O_i computes its partial secret keys by interpolating the subshares s_i^{z,j,b} \in \mathbb{F}_r for $z\in \mathcal{S}$$z = 1, \dots, n$$j=1, \dots, k$ and b=1, \dots, v.
E.g., the fresh partial secret key of the operator O_i for the validator j for the version b is computed as sk_{i}'^{j,b}= \sum\limits_{z\in \mathcal{S}}^{}\lambda_z\cdot s_i^{z,j,b}, where \lambda_z is the appropriate Lagrange coefficient.

The operator O_i computes the set of fresh partial public keys PK'_{partial}:=\{(pk_i'^{j,b})_{i=1, \dots, n';\ j=1,\dots,k; \ b=1, \dots, v}pk_i'^{j,b} = \sum\limits_{z \in \mathcal{S}}^{} \lambda_z\cdot \sum\limits_{\ell=0}^{t'1} {i^{\ell}}\cdot A_{\ell}^{z,j,b}\} using \text{PCOM}_z \ (z \in \mathcal{S}).

The operator O_i obtains a set of
cluster_lock
andvalidator_keystore
versions, i.e.,cluster_lock_b
andvalidator_keystore_b
for b=1,\dots,v.
The aggregator generates a SNARK for proving that the set PK'_{partial} of fresh partial public keys of all operators is computed correctly as follows.
The circuit:
The circuit is over \mathbb{F}_q. The aggregator generates a proof \pi_{\text{pk}}=(A_{\text{pk}},B_{\text{pk}},C_{\text{pk}}), where A_{\text{pk}},C_{\text{pk}}\in \mathbb{G}_1^{\text{out}}, B_{\text{pk}} \in \mathbb{G}_2^{\text{out}}. We will use the hash H_1 : \{0,1\}^* \to \mathbb{F}_{q} for committing the public data.

Private inputs:

indices of all operators (subshare holders), i.e., PI=\{1,\dots, n'\}

\text{PCOM}:=\{\text{PCOM}_i \text{PCOM}_i:=\{(A_0^{i,j,b}, \dots, A_{t'_{}1}^{i,j,b})_{j=1,\dots,k;\ b=1,\dots, v} \in {(\mathbb{G}_1^{\text{in}})}^{kt'v}\}, i\in \mathcal{S} \}, where \mathcal{S} is the set of indices of at least t old operators.

PK'_{partial}:=\{(pk_i'^{j,b}\in \mathbb{G}^{\text{in}}_1)_{i=1, \dots, n'; \ j = 1, \dots, k; \ b = 1, \dots, v}\} is the set of all fresh partial public keys.

PK_{validator}:=\{pk^1, \dots, pk^k \in \mathbb{G}^{\text{in}}_1\} is the set of validatorsâ€™ public keys,
Notice that PK_{validator} has never been changed since the first DKG!


Public inputs:

a commitment to the public keys, i.e., Pub_{\text{pk}} = H_1(PK_{validator}),

a commitment to the \text{PCOM}, i.e., Pub_{\text{com}} := H_1(\text{PCOM})

the lock hashes of the fresh
cluster_lock_b
, i.e., \text{LH}_b, b=1,\dots,v. 
the signature aggregate of the fresh
cluster_lock_b
, i.e., \text{SA}_b, b=1,\dots,v.Note that any verifier should check that the off chain Pub_{\text{pk}} actually corresponds to the public keys stored onchain. Also, note that public keys can be given to the circuit as part of the public inputs, but this approach is more expensive.


Relation R_{\text{pk}}:

Assert that Pub_{\text{pk}} = H_1(PK_{validator})

Assert that Pub_{\text{com}} := H_1(\text{PCOM})

Assert that pk^j= \sum\limits_{i \in \mathcal{S}}^{} \lambda_i\cdot A_0^{i,j,b} for j = 1, \dots, k and b = 1, \dots, v, where \lambda_i is the appropriate Lagrange coefficient with respect to the old operator O_i for i \in\mathcal{S}.

Assert that pk^j = \sum\limits_{i \in \mathcal{G}}^{} {\lambda_i}\cdot pk_i'^{j,b} for j = 1, \dots, k and b = 1, \dots, v, where \lambda_i is the appropriate Lagrange coefficient with respect to the operator O_i and \mathcal{G} is the set of indices of at least t' operators (subshare holders).
Notice that the sets \mathcal{S} is the set of at least t old operators whereas the set \mathcal{G} is the set of at least any t' operators (subshare holders). The corresponding Lagrange coefficients are computed according to these sets. (See the definition)

Assert \textrm{BLS.Verifier}(\text{SA}_b, \text{LH}_b, apk_b)=1, where apk_b is the aggregated public key with respect to the version b, i.e., apk_b := \sum\limits_{i=1}^{n'}\sum\limits_{j=1}^{k} pk_i'^{j,b}.
The above assertion (verification of the aggregated BLS signature on the lock hash) guarantees that each operator has correct partial secret keys for all validators.

The aggregator obtains a Groth16 proof \pi_{\text{pk}} and (Pub_{\text{pk}},Pub_{\text{com}},\text{LH}_b,\text{SA}_b).
F. The wrapper SNARK
We will use a SNARKfriendly hash functions H_1 : \{0,1\}^* \to \mathbb{F}_{q} and Keccak256 (denoted by H_2) for committing to the private inputs. The wrapper circuit is over \mathbb{F}_{\ell}. The aggregator generates a wrapper proof \pi_w=(A_{\text{w}},B_{\text{w}},C_{\text{w}}), where A_{\text{w}},C_{\text{w}}\in \mathbb{G}_1^{\text{w}}, B_{\text{w}} \in \mathbb{G}_2^{\text{w}}. We denote the relations and verification keys for the outer SNARKs and the SNARKs for proving the validity of the public keys as (R_{\text{out}},\texttt{vk}_{\text{out}}) and (R_{{\text{pk}}},\texttt{vk}_{{\text{pk}}}), respectively.

Private inputs:
 \text{PCOM}:=\{\text{PCOM}_z  z \in \mathcal{S}\}
 PK_{validator}:=\{pk^1, \dots, pk^k \in \mathbb{G}^{\text{in}}_1\}
 PD that includes
 indices of all operators (subshare holders), i.e., PI=\{1,\dots, n'\}.
 Pub_{\text{in}}^i for i\in \mathcal{S}.
 Pub_{\text{out}}^i for i\in \mathcal{S}.
 the inner proof \pi_{\text{in}}^i for i\in \mathcal{S}.
 the outer proof \pi_{\text{out}}^i for i\in \mathcal{S}.
 the proof for public keys \pi_{\text{pk}}
 a commitment to \text{PCOM}:=\{\text{PCOM}_z  z \in \mathcal{S}\}, i.e., Pub_{\text{com}} := H_1(\text{PCOM})
 the lock hashes of the fresh
cluster_lock_b
, i.e., \text{LH}_b, b=1,\dots,v.  the signature aggregate of the fresh
cluster_lock_b
, i.e., \text{SA}_b, b=1,\dots,v.

Public inputs:

a commitment to the private inputs, i.e., Pub_{\text{w}} = H_2(PD).

a commitment to the public keys, i.e., Pub_{\text{pk}} = H_1(PK_{validator}).
We make the PD public so that the verifiers can check the validity of Pub_{\text{w}} = H_2(PD). And it should also verify Pub_{\text{pk}} = H_1(PK_{validator}).


Relation R_{w}:

Assert that Pub_{\text{out}}^i=H_1(\text{PCOM}_i) for i=1, \dots, n'.
This is already asserted in the outer circuit. But, we need to be sure that \text{PCOM}_i is a part of \text{PCOM}.

Assert that Pub_{\text{pk}} = H_1(PK_{validator})

Assert that \textrm{Groth16.Verifier}(R_{\text{out}}, \texttt{vk}_{\text{out}}, (PI, Pub_{\text{in}}^i,\pi_{\text{in}}^i, Pub_{\text{out}}^i), \pi^i_{\text{out}})=1 for i\in \mathcal{S}.
We assert that the Groth16 proof composition of the operators are valid, i.e., the old operator O_i correctly evaluated a polynomial whose commitment is \text{PCOM}_i.

Assert that \textrm{Groth16.Verifier}(R_{\text{pk}}, \texttt{vk}_{\text{pk}}, (Pub_{\text{pk}},Pub_{\text{com}},\text{LH}_b,\text{SA}_b), \pi_{\text{pk}})=1 for b= 1, \dots, v.
We assert that the SNARKs for public keys are valid, i.e., the validatorsâ€™ public keys whose hash is Pub_{\text{pk}} are consistent with the commitments \text{PCOM} whose hash is Pub_{\text{com}} and the lock hash is signed by fresh partial secret keys (of all operators) whose interpolation gives the validatorsâ€™ public keys.

Upon obtaining the wrapper proof \pi_{\text{w}}, the aggregator submits the key refresh data, i.e. (\pi_{\text{w}},Pub_{\text{w}},Pub_{\text{pk}},PD), as blob data in an Ethereum blob transaction (using EIP4844).