Skip to content

Commit

Permalink
Point to test vectors rather than reproduce them
Browse files Browse the repository at this point in the history
The current plan is to reproduce the test vectors in the draft once
we're ready for RFC. However the value of these test vectors for
implementers is not clear. It would be better to publish
machine-readable test vectors somewhere, point to it from the
draft, and publish a hash of the test vectors in the draft so that
implementers can use to verify their veracity.

This commit implements the following idea: point to a commit hash for
the draft and describe how to consume the test vectors.

This commit also moves the VDAF test vectors to a directory that is easy
to reference. Namely, we remove the sub-directory based on the version
and add a `vdaf` sub-directory.
  • Loading branch information
cjpatton committed Oct 1, 2024
1 parent 17e90c9 commit b1a6e60
Show file tree
Hide file tree
Showing 19 changed files with 129 additions and 51 deletions.
145 changes: 112 additions & 33 deletions draft-irtf-cfrg-vdaf.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,12 @@ informative:
- ins: H. Lee
date: 2024

TestVectors:
title: "Test vectors for Prio3 and Poplar1"
target: "https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/test_vec/vdaf"
seriesinfo: "commit hash <TODO>"
date: September 2024

--- abstract

This document describes Verifiable Distributed Aggregation Functions (VDAFs), a
Expand Down Expand Up @@ -5695,54 +5701,127 @@ useful feedback on and contributions to the spec.
# Test Vectors {#test-vectors}
{:numbered="false"}

(TO BE REMOVED BY RFC EDITOR: machine-readable test vectors can be found at
https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/poc/test_vec.)
> TODO Update the reference in {{TestVectors}} by replacing `<TODO>` with
> the commit hash with the final version of the test vectors.)

Test vectors cover the generation of input shares and the conversion of input
shares into output shares. Vectors specify the verification key, measurements,
aggregation parameter, and any parameters needed to construct the VDAF. (For
example, for `Prio3Sum`, the user specifies the number of bits for representing
each summand.)
The test vectors are available at {{TestVectors}}. The directory contains a set
of JSON files. Each file contains a test vector for an instance of `Vdaf`
({{vdaf}}). A test vector covers sharding, preparation, aggregation, and
unsharding of each of several measurements. The test vector schema is defined
below.

Byte strings are encoded in hexadecimal. To make the tests deterministic, the
random inputs of randomized algorithms were fixed to the byte sequence starting
with `0`, incrementing by `1`, and wrapping at `256`:
## Schema
{:numbered="false"}

~~~
0, 1, 2, ..., 255, 0, 1, 2, ...
~~~
`ctx`:
: The application context string encoded in hexadecimal.

`verify_key`:
: The verification key encoded in hexadecimal.

`agg_param`:
: The aggregation parameter of type `Vdaf.AggParam`.

`prep`:
: A list of objects with the following schema:

`measurement`:
: The measurement of type `Vdaf.Measurement`.

`nonce`:
: The nonce encoded in hexadecimal.

`rand`:
: The sharding randomness encoded in hexadecimal.

`public_share`:
: The expected public share encoded in hexadecimal.

`input_shares`:
: The expected list of input shares, each incoded in hexadecimal.

`prep_shares`:
: The expected list of prep shares generated by each Aggregator at each
round of preparation, encoded in hexadecimal.

`prep_messages`:
: The expected list of prep messages for each round of preparation, encoded
in hexadecimal.

`out_shares`:
: The expected list of output shares, encoded in hexadecimal.

`agg_shares`:
: The expected aggregate shares encoded in hexadecimal.

`agg_result`:
: The expected aggregate result of type `Vdaf.AggResult`.

The schema also includes whatever parameters are required to instantiate the
VDAF. These are listed in the subsections below.

## Prio3Count {#testvec-prio3count}
### Prio3Count
{:numbered="false"}

> TODO Copy the machine readable vectors from the source repository
> (https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/poc/test_vec) and
> format them for humans.
`shares`:
: The number of shares, an integer.

## Prio3Sum {#testvec-prio3sum}
### Prio3Sum
{:numbered="false"}

> TODO Copy the machine readable vectors from the source repository
> (https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/poc/test_vec) and
> format them for humans.
`shares`:
: The number of shares, an integer.

`max_measurement`:
: The largest measurement, an integer. Each element is in range
`range(max_measurement+1)`.

## Prio3SumVec {#testvec-prio3sumvec}
### Prio3SumVec
{:numbered="false"}

> TODO Copy the machine readable vectors from the source repository
> (https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/poc/test_vec) and
> format them for humans.
`shares`:
: The number of shares, an integer.

`length`:
: The lengh of the vector, an integer.

## Prio3Histogram {#testvec-prio3histogram}
`chunk_length`:
: the length of each vector chunk, an integer.

`bits`:
: the bit length of each element of the vector, an integer. each element is in
`range(2 ** bits)`.

### Prio3Histogram
{:numbered="false"}

> TODO Copy the machine readable vectors from the source repository
> (https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/poc/test_vec) and
> format them for humans.
`shares`:
: The number of shares, an integer.

`length`:
: The lengh of the vector, an integer.

`chunk_length`:
: the length of each vector chunk, an integer.

### Prio3MultihotCountVec
{:numbered="false"}

`shares`:
: The number of shares, an integer.

`length`:
: The lengh of the vector, an integer.

`chunk_length`:
: the length of each vector chunk, an integer.

`max_weight`:
: The largest vector weight, an integer. The sum of the elements must be in
`range(max_weight+1)`.

## Poplar1 {#testvec-poplar1}
### Poplar1 {#poplar1-test-vec-param}
{:numbered="false"}

> TODO Copy the machine readable vectors from the source repository
> (https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/poc/test_vec) and
> format them for humans.
`bits`:
: The length of each input, an integer.
28 changes: 14 additions & 14 deletions poc/gen_test_vec.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import json
import os

from vdaf_poc.common import VERSION, print_wrapped_line
from vdaf_poc.common import print_wrapped_line
from vdaf_poc.field import Field128
from vdaf_poc.idpf import Idpf
from vdaf_poc.test_utils import gen_test_vec_for_vdaf, test_vec_gen_rand
from vdaf_poc.xof import Xof

# The path where test vectors are generated.
TEST_VECTOR_PATH = os.environ.get('TEST_VECTOR_PATH',
'../test_vec/{:02}'.format(VERSION))

TEST_VECTOR_PATH = os.environ.get('TEST_VECTOR_PATH', '../test_vec/')

# IDPF


def gen_test_vec_for_idpf(idpf: Idpf,
alpha: tuple[bool, ...],
test_vec_instance: int) -> None:
Expand Down Expand Up @@ -91,42 +90,43 @@ def gen_test_vec_for_xof(cls: type[Xof]) -> None:
from vdaf_poc import idpf_bbcggi21, vdaf_poplar1, vdaf_prio3, xof

ctx = b'some application'
vdaf_test_vec_path = TEST_VECTOR_PATH + "/vdaf/"

# Prio3 variants
gen_test_vec_for_vdaf(
TEST_VECTOR_PATH,
vdaf_test_vec_path,
vdaf_prio3.Prio3Count(2),
None,
ctx,
[1],
0,
)
gen_test_vec_for_vdaf(
TEST_VECTOR_PATH,
vdaf_test_vec_path,
vdaf_prio3.Prio3Count(3),
None,
ctx,
[1],
1,
)
gen_test_vec_for_vdaf(
TEST_VECTOR_PATH,
vdaf_test_vec_path,
vdaf_prio3.Prio3Sum(2, 255),
None,
ctx,
[100],
0,
)
gen_test_vec_for_vdaf(
TEST_VECTOR_PATH,
vdaf_test_vec_path,
vdaf_prio3.Prio3Sum(3, 255),
None,
ctx,
[100],
1,
)
gen_test_vec_for_vdaf(
TEST_VECTOR_PATH,
vdaf_test_vec_path,
vdaf_prio3.Prio3SumVec(2, 10, 8, 9),
None,
ctx,
Expand All @@ -138,7 +138,7 @@ def gen_test_vec_for_xof(cls: type[Xof]) -> None:
0,
)
gen_test_vec_for_vdaf(
TEST_VECTOR_PATH,
vdaf_test_vec_path,
vdaf_prio3.Prio3SumVec(3, 3, 16, 7),
None,
ctx,
Expand All @@ -150,23 +150,23 @@ def gen_test_vec_for_xof(cls: type[Xof]) -> None:
1,
)
gen_test_vec_for_vdaf(
TEST_VECTOR_PATH,
vdaf_test_vec_path,
vdaf_prio3.Prio3Histogram(2, 4, 2),
None,
ctx,
[2],
0,
)
gen_test_vec_for_vdaf(
TEST_VECTOR_PATH,
vdaf_test_vec_path,
vdaf_prio3.Prio3Histogram(3, 11, 3),
None,
ctx,
[2],
1,
)
gen_test_vec_for_vdaf(
TEST_VECTOR_PATH,
vdaf_test_vec_path,
vdaf_prio3.Prio3MultihotCountVec(2, 4, 2, 2),
None,
ctx,
Expand Down Expand Up @@ -203,7 +203,7 @@ def gen_test_vec_for_xof(cls: type[Xof]) -> None:
measurements: list[tuple[bool, ...]] = [(True, True, False, True)]
for (test_level, prefixes) in tests:
gen_test_vec_for_vdaf(
TEST_VECTOR_PATH,
vdaf_test_vec_path,
vdaf_poplar1.Poplar1(4),
(test_level, prefixes),
ctx,
Expand Down
7 changes: 3 additions & 4 deletions poc/vdaf_poc/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,17 +141,16 @@ def gen_test_vec_for_vdaf(
(public_share, input_shares) = \
vdaf.shard(ctx, measurement, nonce, rand)

pub_share_hex = vdaf.test_vec_encode_public_share(public_share).hex()
prep_test_vec: VdafPrepTestVectorDict[Measurement] = {
'measurement': measurement,
'nonce': nonce.hex(),
'rand': rand.hex(),
'public_share': pub_share_hex,
'input_shares': [],
'prep_shares': [[] for _ in range(vdaf.ROUNDS)],
'prep_messages': [],
'out_shares': [],
'rand': rand.hex(),
'public_share': vdaf.test_vec_encode_public_share(
public_share
).hex()
}
for input_share in input_shares:
prep_test_vec['input_shares'].append(
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit b1a6e60

Please sign in to comment.