# FROST notes
###### Links:
[FROST](https://eprint.iacr.org/2020/852.pdf)
[How to prove Schnorr assuming Schnorr](https://eprint.iacr.org/2021/1375.pdf)
[Concurrent signing forgery attack](https://eprint.iacr.org/2018/417.pdf)
[Craige's forgery attack against Feldman's VSS](https://www.jcraige.com/vss-forgery)
[ROAST](https://eprint.iacr.org/2022/550.pdf) robust signing, running concurrent sessions for failover
[ICE FROST](https://eprint.iacr.org/2021/1658) robust keygen
[IETF FROST](https://datatracker.ietf.org/doc/draft-irtf-cfrg-frost/)
[NIDKG](https://eprint.iacr.org/2021/339.pdf)
[Fifty shades of FROST](https://eprint.iacr.org/2022/833.pdf)
###### Questions
### KeyGen:
#### Round 1: _prove knowledge of your secret commitment_
##### Sample a secret
Participant $P_i$ samples $t$ random scalars $a_{i,0}, a_{i, 1}, ... a_{i, t-1}$ and constructs a polynomial $f_i(x) = a_{i,0} + a_{i,1}x + a_{i,2}x^2... + a_{i,(t-1)}x^{t-1}$.
##### Create a proof of knowledge of the constant-term
Participant $P_i$ samples a random nonce $k \leftarrow \mathbb{F}_q$, computes a commitment to that nonce $R_i := [k]G$, and a challenge $c_i := H(i, \Phi, [a_{i,0}]G, R_i)$ where $\Phi$ is a [_context string_]() (TODO: is this more than a domain separator?).
They create $\mu_i = k + a_{i,0}\cdot c_i$, and $\sigma_i = (R_i, \mu_i)$.
##### Public commitment
Participant $P_i$ computes a public commitment to the coefficient of its polynomial: $\vec{C_i} = \langle\phi_{i,0}, \phi_{i,1}, .., \phi_{i, (t-1)}\rangle$.
Remark: note that this enables another participant to homomorphically evaluate $f_i$ at an arbitrary point $w$ by computing: $\sum_{k=0}^{t-1} \phi^{w^k}_{i,k}$, this will prove useful in the key generation step.
##### Broadcast to your peers
Participant $P_i$ broadcasts $(\sigma_i, \vec{C_i})$ to the rest of the cohorts, and expects its peers to reciprocate.
##### Verify your peers
Participant $P_i$ receives $(\sigma_l, \vec{C_l})$ from $P_l$, reconstructs the challenge $c_l = H(l, \Phi, \phi_{l,0}, R_l)$ verifies that:
$\sigma_l = (R_l, \mu_l)$ by checking that $[\mu_l]G+[c_l]\phi_{l,0} \stackrel{?}{=} R_l$.
#### Round 2: _generate the cohort's signing key_
##### Constructing their secret-share
Participant $P_i$ computes $(i, f_i(i))$
##### Broadcasting peers' secret-share
For each peer $P_l$, participant $P_i$ sends $(l, f_i(l))$
##### Verifiy their own peer generated secret share
For each peer $P_l$, participant $P_i$ _receives_ a tuple $(i, f_l(i))$, the participant needs to verify that untrusted share by homomorphically evaluating $f_l(i)$ using $\vec{C_l}$:
$f_l(i) \stackrel{?}{=} \sum_{j=0}^{t-1} \phi_{l,j}^{i^j}$
##### Compute the local signing key
Participant $P_i$ computes their local private key from the shares it receives from its peers:
$s_i = \sum_{j=1}^{n} f_j(i)$
##### Compute the public verification share
Participant $P_i$ can compute their public verification share:
$Y_i = [s_i]G$
##### Cache peers' verification share
Participant $P_i$ can compute the public verification share of another participant $P_l$:
$Y_l := \sum_{a=1}^n \sum_{j=0}^{t-1} \phi_{a,j}^{l^j} (= [\sum_{a=1}^n f_a(l)]G)$
##### Compute the group public key
$Y = \sum^{n}_{j=1} \phi_{j,0} (= [\sum_{j=1}^n f_j(0)]G)$
## API shape
```rust
struct ThresholdSigner {
public_key: Element,
}
enum State {
Init,
KeyGenRoundOne,
KeyGenRoundTwo,
Ready,
}
struct Participant<State> {
identifier: usize,
nonce: Fr,
secrets: Vec<Fr>,
signing_key: SigningKey,
verification_key: VerificationKey,
peer_cache: Vec<VerificationKey>,
}
```
```go
│
│
▼
┌─────┐
┌──────┤Init │
│ └─────┘
│
│
└────► ┌───────────────┐ each participant has:
│KeyGenRoundOne │ a local polynomial of degree t-1
┌───── └───────────────┘ a local random nonce
│
│
│
│
│
└────► ┌───────────────┐ every participant has generated
│KeyGenRoundTwo │ a public commitment vector
┌───── └───────────────┘ a valid PoK
│
│
│
│
│
│ ┌──────┐ each participant has:
└────► │Ready │ a local signing share
└──────┘ a local verification share
a cohort verification key
```
## Threshold signing
### Preprocessing
The preprocessing step consist of having every participant, precompute and commit to $\pi$ tuples of single-use nonces, where $\pi \geq 1$ is a protocol parameter.
##### Sampling single-use nonces:
Participant $P_i$ samples $1 \leq j \leq \pi$ single use nonces: $n_{i,j} := (d_{i,j}, e_{i,j})$ and caches them in a secure location.
##### Commitments
Participant $P_i$ prepares public commitments of every tuple, for $1 \leq j \leq \pi$:
$N_{i,j} := (D_{i,j}, E_{i,j}) = ([d_{i,j}]G, [e_{i,j}]G)$
##### Broadcast
Participant $P_i$ publishes $\langle N_{i,0}, N_{i,1}, ..., N_{i, \pi}\rangle$
```rust
struct Nonce {
// idea: embed an internal unique identifier
// so that nonces from a previous aggregation round
// cannot be used accidentally
inner: Fr,
}
impl Nonce {
pub fn sample(rng: OsRng) -> Self;
pub fn commit(basepoint: Element) -> Commitment;
pub fn use(self) -> Fr;
}
```
### Signing
We denote $P_{leader}$ the leader for the current round $k$ of signing message $m$.
Remark: as far as I can tell every participant can assume the position of leader, and an implementation could leverage that fact to avoid round-trips between leader/participants when building the nonce-list.
##### Round leader fetch nonces
For round $k$, $P_{leader}$ fetches every participant's committed nonce and constructs and ordered list $B := \langle (i, N_{i,k})\rangle_{0\leq i \leq n}$
##### Round leader broadcasts the nonce-list
$P_{leader}$ sends $(m, B)$ to every participant.
##### Participants validates input
Participant $P_i$ receives $(m, B)$ from $P_{leader}$ and:
- validates the message $m$ (TODO: what if you dont?)
- checks that $N_{i,k} \in \mathbb{G^*} \times \mathbb{G^*}$
##### Participants prepare signing
1. $P_i$ computes the _set_ of binding values $\langle \rho_l = H_1(l, m, B) \rangle_{P_l \in S}$
2. $P_i$ derives the group commitment $R = \sum_{P_l \in S} D_l + [\rho_l]E_l$
3. $P_i$ computes the challenge $c = H_2(R, Y, m)$
Now, $P_i$ is ready to compute its signature share.
##### Computing the signature share
$z_i = d_i + (e_i \cdot \rho_i) + \lambda_i \cdot s_i \cdot c$
where $\lambda_i$ is the lagrange coefficient. AFAICT, it's probably optional
```
nonce-commitment list
┌─────┬─────┬─────┐
│ D_1 │ │D_pi │ message
│ │ ... │ │ ┌───┐
│ E_1 │ │E_pi │ │ m │
└─────┴───┬─┴─────┘ └─┬─┘
│ │
│ │
│ │
│ │
│ │
participant index └────┐ ┌──────┤
─────────────────┐ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
▼ ▼ ▼ │
│
───────────┬─────────── │
│ │
│ │
▼ │
┌──────────────────┐ │
│ │ │
│r_l = H_1(l, m, B)│ │
│ │ │
└──────────────────┘ │
binding value for P_l │
│
│ │
│ │
┌─────────────────┘ └──────────────────────┐
│ │
│ │
│ │
│ │
│ ┌───────────────────────────────┐ │
│ │ Y = \sum_{j=1}^{n} \phi_{j,0} │ │
│ └─────────────────────┬─────────┘ │
│ Cohort public key │ │
│ │ │
▼ └─────┐ │
│ │
group commitment │ │
┌────────────────────────────────────────────────────────┐ │ │
│ R = D_1 + [r_1]E_1 + ... + D_alpha + [r_alpha]E_alpha │ │ │
└────────────────────────────────────────────────────────┘ │ │
│ │
│ │ │
└───────────┐ ┌────────────────────┘ │
│ │ │
│ │ ┌──────────────────────┘
│ │ │
│ │ │
▼ ▼ ▼
─────────────┬───────────────
│
│
│
▼
┌───────────────────────┐
│ c = H_2(R, Y, m) │
└───────────────────────┘
challenge
```
##### Group signing
Participant $P_i$
## Roast extension