---
# System prepended metadata

title: VRF upgrade (v6 -> v9)

---

# VRF upgrade (v6 -> v9)

# What's the difference
1. `ECVRF_hash_to_curve_elligator2_25519` -> `ECVRF_hash_to_curve_h2c_suite`
2. `hash_to_curve` no longer takes a suite_string as explicit input
3. `decode_proof` takes an extra 0-byte as input for domain separation
4. `hash_points` has minor differences

## 1. encode_to_curve

#### Implementation steps
```
 encode_to_curve(msg)
 Input: msg, an arbitrary-length byte string.
 Output: P, a point in G.
 
 Steps:
 1. u = hash_to_field(msg, 1)
 2. Q = map_to_curve(u[0])
 3. P = clear_cofactor(Q)
 4. return P
```

#### `hash_to_field(msg, count=1)`

```
 Parameters:
 - DST ("ECVRF_edwards25519_XMD:SHA-512_ELL2_NU_0x04")
 - F, a finite field of characteristic p and order q = p^m. (?)
 - q, p^m = (2^255 - 19)^1
 - p, (2^255 - 19)
 - m, (1)
 - L = ceil((ceil(log2(p)) + k) / 8) = (48)
 - expand_message, a function that expands a byte string and
 domain separation tag into a uniformly random byte string ("expand_message_xmd")
 
 Inputs:
 - msg, a byte string containing the message to hash.
 - count, the number of elements of F to output. (1)
 
 Outputs:
 - (u_0, ..., u_(count - 1)), a list of field elements.
 
 Steps:
 1. len_in_bytes = count * m * L
 2. uniform_bytes = expand_message(msg, DST, len_in_bytes)
 // count = 1 -> Do 1 time -> elm_offset = 0 -> return u_0
 3. for i in (0, ..., count - 1):
 4.   for j in (0, ..., m - 1):
 5.     elm_offset = L * (j + i * m)
 6.     tv = substr(uniform_bytes, elm_offset, L)
 7.     e_j = OS2IP(tv) mod p
 8.   u_i = (e_0, ..., e_(m - 1))
 9. return (u_0, ..., u_(count - 1))
```

##### `expand_message_xmd(msg, DST, len_in_bytes)`
```
 Parameters:
 - H, a hash function (sha512)
 - b_in_bytes, b / 8 for b the output size of H in bits. (64)
 For example, for b = 256, b_in_bytes = 32.
 - r_in_bytes, the input block size of H, measured in bytes (see
 discussion above). For example, for SHA-256, r_in_bytes = 64.
 Input:
 - msg, a byte string.
 - DST, a byte string of at most 255 bytes.
 See below for information on using longer DSTs.
 - len_in_bytes, the length of the requested output in bytes. (64)
 Output:
 - uniform_bytes, a byte string.
 Steps:
 1. ell = ceil(len_in_bytes / b_in_bytes)
 2. ABORT if ell > 255
 3. DST_prime = DST || I2OSP(len(DST), 1)
 4. Z_pad = I2OSP(0, r_in_bytes)
 5. l_i_b_str = I2OSP(len_in_bytes, 2)
 6. msg_prime = Z_pad || msg || l_i_b_str || I2OSP(0, 1) || DST_prime
 7. b_0 = H(msg_prime)
 8. b_1 = H(b_0 || I2OSP(1, 1) || DST_prime)
 // In our case ell = 1, so it'll skip the loop
 9. for i in (2, ..., ell):
 10.   b_i = H(strxor(b_0, b_(i - 1)) || I2OSP(i, 1) || DST_prime)
 11.   uniform_bytes = b_1 || ... || b_ell
 12.return substr(uniform_bytes, 0, len_in_bytes)
```

---

### `map_to_curve(u)`
```
map_to_curve_elligator2_edwards(u)
 Input: u, an element of F.
 Output: (v, w), a point on E.
 1. (s, t) = map_to_curve_elligator2(u) # (s, t) is on M
 2. (v, w) = rational_map(s, t) # (v, w) is on E
 3. return (v, w)
```

#### `map_to_curve_elligator2(u)`
```
Constants:
 * J, (486662)
 * K, (1)
 * Z, (2)
 
 Sign of t: this mapping fixes the sign of t as specified in [BHKL13].
 No additional adjustment is required.
 
 Exceptions: The exceptional case is Z * u^2 == -1, i.e., 1 + Z * u^2
 == 0. Implementations must detect this case and set x1 = -(J / K).
 Note that this can only happen when q = 3 (mod 4).
 
 Operations:
 1. x1 = -(J / K) * inv0(1 + Z * u^2)
 2. If x1 == 0, set x1 = -(J / K)
 3. gx1 = x1^3 + (J / K) * x1^2 + x1 / K^2
 4. x2 = -x1 - (J / K)
 // gx2 might not happen? (Because gx1 is always square.)
 5. gx2 = x2^3 + (J / K) * x2^2 + x2 / K^2
 6. If is_square(gx1), set x = x1, y = sqrt(gx1), and sgn0(y) == 1.
 7. Else set x = x2, y = sqrt(gx2), and sgn0(y) == 0.
 // -----------
 8. s = x * K
 9. t = y * K
 10. return (s, t)
```

#### `rational_map`
```
The birational maps are:
 (u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)
 (x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))
```

---

### `clear_cofactor`

```
The clear_cofactor function is parameterized by a scalar h_eff.
* h_eff = 8

 Specifically,
 clear_cofactor(P) := h_eff * P
 
 where * represents scalar multiplication. When a curve does not
 support a fast cofactor clearing method, h_eff = h and the cofactor
 MUST be cleared via scalar multiplication.
```

---

## 2. de



## Utility function

### `I2OSP(x, xLen)`

```
 I2OSP converts a nonnegative integer to an octet string of a
 specified length.
 
 Input:
 x nonnegative integer to be converted
 xLen intended length of the resulting octet string
 
 Output:
 X corresponding octet string of length xLen
 Error: "integer too large"
 
 Steps:
 1. If x >= 256^xLen, output "integer too large" and stop.
 2. Write the integer x in its unique xLen-digit representation in
 base 256:
 
 x = x_(xLen-1) 256^(xLen-1) + x_(xLen-2) 256^(xLen-2) + ...
 + x_1 256 + x_0,
 where 0 <= x_i < 256 (note that one or more leading digits
 will be zero if x is less than 256^(xLen-1)).
 
 3. Let the octet X_i have the integer value x_(xLen-i) for 1 <= i
 <= xLen. Output the octet string
 
 X = X_1 X_2 ... X_xLen.
```

### `OS2IP(X)`

```
 OS2IP converts an octet string to a nonnegative integer.

 Input: X octet string to be converted
 Output: x corresponding nonnegative integer
 
 Steps:
 1. Let X_1 X_2 ... X_xLen be the octets of X from first to last,
 and let x_(xLen-i) be the integer value of the octet X_i for 1
 <= i <= xLen.
 
 2. Let x = x_(xLen-1) 256^(xLen-1) + x_(xLen-2) 256^(xLen-2) +
 ... + x_1 256 + x_0.
 
 3. Output x.
 ```
 
### `sgn0(x)`
```
* sgn0(x): This function returns either 0 or 1 indicating the "sign"
 of x, where sgn0(x) == 1 just when x is "negative". (In other
 words, this function always considers 0 to be positive.)
 Section 4.1 defines this function and discusses its
 implementation.
```

### `is_sqaure(x)`

```
is_square(x): This function returns True whenever the value x is a
 square in the field F. By Euler’s criterion, this function can be
 calculated in constant time as
 is_square(x) := { True, if x^((q - 1) / 2) is 0 or 1 in F;
 { False, otherwise.
```
 
 ## Question
- `"ECVRF_" || "edwards25519_XMD:SHA-512_ELL2_NU_" || suite_string` when do we use it and is it DST?