---
# System prepended metadata

title: ed25519 on gnark - challenges

---

# ed25519 on gnark - challenges

We are implementing a ed25519 circuit that verifies multiple signatures.

```go

type Ed25519Verfier struct {
	Rc [N][32]uints.U8           `gnark:",public"`
	S  [N]curve_ed25519.ElementO `gnark:",public"`
	Ac  [N][32]uints.U8   `gnark:",public"`
	Msg [N][M_LENGTH]uints.U8 `gnark:",public"`
}
```

Essentially, the input for the verifier is:
```json
[
    [pubkey_1, signature_1, message_1], // where message     length == M_LENGTH
...
    [pubkey_N, signature_N, message_N],
]
```

and it verifies them one by one, and returns true if all signatures are correct.

As per [`ed25519` spec](https://en.wikipedia.org/wiki/EdDSA#Ed25519) this is an algorithm that uses the `ed25519` curve, with the `sha2 512` hashing function.

Our original implementation was incorrect, as we did not realize that we needed to use the `sha2 512`, and we did it with the gadget provided by gnark, which is the [`sha2 256`](https://github.com/Consensys/gnark/tree/master/std/hash/sha2).

We can then always implement the gadget, and replace the code with the correct one. However, this is a substantial lift that will take us several days (or weeks) to do properly.

We are then, trying to avoid this and find a solution that can let us use this circuit without having to implement this gadget.

## Our potential solution

What if we don't calculate `sha2 512` inside of the circuit? If we could somehow avoid this, then we are done.

Leveraging gnark's [hints]( https://docs.gnark.consensys.io/HowTo/write/hints) we can do calculations off-circuit, and pass them. This is not for free, as there needs to be a validation that this numbers are correct, otherwise the circuit would be unsound.

Our proposal is to change the input to:

```json
[
    [pubkey_1, signature_1, message_1], // where message     length == M_LENGTH
...
    [pubkey_N, signature_N, message_N],
    sha2_256(sha512(message_1), sha512(message_2), ...sha512(message_N))
]
```

where `sha2_256(sha512(message_1), sha512(message_2), ...sha512(message_N))` is called `precomputed_hash`.

Then, inside the circuit we offload the calculation of the sha512(message_i) to a hint. And at the very end, inside inside the circuit, it verifies that:

```
sha2_256(hint1, hint2, ..., hint2) == precomputed_hash
```

Our _hope_ is that this doesn't make the circuit unsound.