Skip to content

Commit

Permalink
IDPF: Simplify the public share encoding (*)
Browse files Browse the repository at this point in the history
Unzip the seeds, control bits, and payloads and encode them separately.
This significantly reduces the complexity of the spec in TLS syntax.
  • Loading branch information
cjpatton committed Sep 6, 2024
1 parent 598455e commit cc87587
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 50 deletions.
30 changes: 10 additions & 20 deletions draft-irtf-cfrg-vdaf.md
Original file line number Diff line number Diff line change
Expand Up @@ -4784,8 +4784,9 @@ network while executing `Poplar1`. It is RECOMMENDED that implementations
provide serialization methods for them.

Message structures are defined following {{Section 3 of !RFC8446}}). In the
remainder we use `Fi` as an alias for `poplar1.idpf.field_inner.ENCODED_SIZE`
and `Fl` as an alias for `poplar1.idpf.field_leaf.ENCODED_SIZE`.
remainder we use `Fi` as an alias for `poplar1.idpf.field_inner.ENCODED_SIZE`,
`Fl` as an alias for `poplar1.idpf.field_leaf.ENCODED_SIZE`, and `B` as an
alias for `poplar1.idpf.BITS`.

Elements of the inner field are encoded in little-endian byte order (as defined
in {{field}}) and are represented as follows:
Expand All @@ -4811,31 +4812,20 @@ of "correction words". A correction word has three components:
3. the payload of type `list[Field64]` for the first `BITS-1` words and
`list[Field255]` for the last word.

The encoding is straightforward, except that the control bits are packed as
tightly as possible. The encoded public share is structured as follows:
The encoding is a straightforward structure of arrays, except that the control
bits are packed as tightly as possible. The encoded public share is structured
as follows:

~~~ tls-presentation
struct {
opaque seed[poplar1.idpf.KEY_SIZE];
Poplar1FieldInner payload[Fi * poplar1.idpf.VALUE_LEN];
} Poplar1CWSeedAndPayloadInner;

struct {
opaque seed[poplar1.idpf.KEY_SIZE];
Poplar1FieldLeaf payload[Fl * poplar1.idpf.VALUE_LEN];
} Poplar1CWSeedAndPayloadLeaf;

struct {
opaque packed_control_bits[packed_len];
Poplar1CWSeedAndPayloadInner inner[Ci * (poplar1.idpf.BITS-1)];
Poplar1CWSeedAndPayloadLeaf leaf;
opaque seed[poplar1.idpf.KEY_SIZE*B];
Poplar1FieldInner payload_inner[Fi*poplar1.idpf.VALUE_LEN*(B-1)];
Poplar1FieldLeaf payload_leaf[Fl*poplar1.idpf.VALUE_LEN];
} Poplar1PublicShare;
~~~

Here `Ci` denotes the length of `Poplar1CWSeedAndPayloadInner` and
`packed_len = (2*Poplar1.Idpf.BITS + 7) // 8` is the length of the packed
control bits.

Here `packed_len = (2*B + 7) // 8` is the length of the packed control bits.
Field `packed_control_bits` is encoded with the following function:

~~~ python
Expand Down
52 changes: 27 additions & 25 deletions poc/vdaf_poc/idpf_bbcggi21.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import itertools
from typing import Sequence, TypeAlias, cast

from vdaf_poc.common import format_dst, vec_add, vec_neg, vec_sub, xor
from vdaf_poc.common import format_dst, front, vec_add, vec_neg, vec_sub, xor
from vdaf_poc.field import Field, Field2, Field64, Field255
from vdaf_poc.idpf import Idpf
from vdaf_poc.xof import Xof, XofFixedKeyAes128, XofTurboShake128
Expand Down Expand Up @@ -283,40 +283,42 @@ def current_xof(self,
def encode_public_share(
self,
public_share: list[CorrectionWord]) -> bytes:
(seeds, ctrl, payloads) = zip(*public_share)
encoded = bytes()
control_bits = list(itertools.chain.from_iterable(
cw[1] for cw in public_share
))
encoded += pack_bits(control_bits)
for (level, (seed_cw, _, w_cw)) \
in enumerate(public_share):
field = cast(type[Field], self.current_field(level))
encoded += seed_cw
encoded += field.encode_vec(cast(list[Field], w_cw))
encoded += pack_bits(list(itertools.chain.from_iterable(ctrl)))
for seed in seeds:
encoded += seed
for payload in payloads[:-1]:
encoded += self.field_inner.encode_vec(payload)
encoded += self.field_leaf.encode_vec(payloads[-1])
return encoded

def decode_public_share(
self,
encoded: bytes) -> list[CorrectionWord]:
l = (2 * self.BITS + 7) // 8
encoded_ctrl, encoded = encoded[:l], encoded[l:]
control_bits = unpack_bits(encoded_ctrl, 2 * self.BITS)
public_share = []
ctrl = []
(encoded_ctrl, encoded) = front((2 * self.BITS + 7) // 8, encoded)
flattened_ctrl = unpack_bits(encoded_ctrl, 2 * self.BITS)
for level in range(self.BITS):
ctrl.append((
flattened_ctrl[2 * level],
flattened_ctrl[2 * level + 1],
))
seeds = []
for _ in range(self.BITS):
(seed, encoded) = front(self.KEY_SIZE, encoded)
seeds.append(seed)
payloads = []
for level in range(self.BITS):
field = self.current_field(level)
ctrl_cw = (
control_bits[level * 2],
control_bits[level * 2 + 1],
)
l = XofFixedKeyAes128.SEED_SIZE
seed_cw, encoded = encoded[:l], encoded[l:]
l = field.ENCODED_SIZE * self.VALUE_LEN
encoded_w_cw, encoded = encoded[:l], encoded[l:]
w_cw = field.decode_vec(encoded_w_cw)
public_share.append((seed_cw, ctrl_cw, w_cw))
(encoded_payload, encoded) = front(
field.ENCODED_SIZE * self.VALUE_LEN,
encoded)
payload = field.decode_vec(encoded_payload)
payloads.append(payload)
if len(encoded) != 0:
raise ValueError('trailing bytes')
return public_share
return list(zip(seeds, ctrl, payloads))

def test_vec_encode_public_share(self, public_share: list[CorrectionWord]) -> bytes:
return self.encode_public_share(public_share)
Expand Down
2 changes: 1 addition & 1 deletion test_vec/12/IdpfBBCGGI21_0.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,5 @@
"101112131415161718191a1b1c1d1e1f"
],
"nonce": "000102030405060708090a0b0c0d0e0f",
"public_share": "9b45026eb4eb0f90256989d33b41b900b2e14171b1cc1f0226c042fd9ce24afda5b8b836664c7a95027be944d399175d19a4b478319b96ce826fc2de8a85d67ba27359c6bb3177b626aa1491dd7278f0fb1c0dfff4d3345e10f7ed286e36cfe49a99ec6a29677bbeb50a27962201ad50f513794f29915778b3a384552db1ffacd11ac7c883ee5676d50cb37664c64407197ad9915c61e693c2d2cfab00d02e2343be64d65d5e60353553c0cc8191486af13ede8eb3e9a3174f16154e9748967d02b75414e4468e0df119012938e2bb2f604c86f877ffe777fec5444b3c90f045cb3ae6a89934a245ac73dc862d87d8e6a71636182ac4e12e1ce81b6a7b5a301ab177b8f2a64ab6f3dbbf0f5d3a7e4e2f35bb4a0a58d0f095288fa0776177213d2ebad84a2c9a9b3077039cfdc066c6b0f565381d4a829ac64735a030686d33ee4c22533864816e8a945d55c867fa6563898e33cf858e5489e4d1b514ee82ac7622ce12cdfe1e2d95215910ec6345290798a470"
"public_share": "9b45026eb4eb0f90256989d33b41b900b2e14136664c7a95027be944d399175d19a4b4c6bb3177b626aa1491dd7278f0fb1c0d6a29677bbeb50a27962201ad50f51379c883ee5676d50cb37664c64407197ad9d65d5e60353553c0cc8191486af13ede14e4468e0df119012938e2bb2f604c86a89934a245ac73dc862d87d8e6a71636f2a64ab6f3dbbf0f5d3a7e4e2f35bb4a4a2c9a9b3077039cfdc066c6b0f5653871b1cc1f0226c042fd9ce24afda5b8b878319b96ce826fc2de8a85d67ba27359fff4d3345e10f7ed286e36cfe49a99ec4f29915778b3a384552db1ffacd11ac7915c61e693c2d2cfab00d02e2343be648eb3e9a3174f16154e9748967d02b754f877ffe777fec5444b3c90f045cb3ae6182ac4e12e1ce81b6a7b5a301ab177b80a58d0f095288fa0776177213d2ebad81d4a829ac64735a030686d33ee4c22533864816e8a945d55c867fa6563898e33cf858e5489e4d1b514ee82ac7622ce12cdfe1e2d95215910ec6345290798a470"
}
2 changes: 1 addition & 1 deletion test_vec/12/Poplar1_0.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"9418b5e770f95412"
]
],
"public_share": "58a20d5e7eb4d586bf8c9c6a14e9e5265d7db6f9955cfea1fdae57cafbf001412abed2ad41e87ccb7df6eea8cdc5c6d35cebd1e8a163804e91f2f1280a61de836386feb9286f4ee02e32c5230f69e833b035e92ee3e6e1a471ae849d6a1cf7ac2afe6c06e0f0275b67ee6cb9f5d18c891bc463b7f13ff67a71e090ae40e69d60faf81cc33067e1add9f8a47ff0f4a12537f7f0ad5d7afefb23d8c037c6ffc6af1583b2d805a346c6e13cfc8465de906e7d",
"public_share": "58a20d5e7eb4d586bf8c9c6a14e9e5265dbed2ad41e87ccb7df6eea8cdc5c6d35c86feb9286f4ee02e32c5230f69e833b0fe6c06e0f0275b67ee6cb9f5d18c891b7db6f9955cfea1fdae57cafbf001412aebd1e8a163804e91f2f1280a61de836335e92ee3e6e1a471ae849d6a1cf7ac2ac463b7f13ff67a71e090ae40e69d60faf81cc33067e1add9f8a47ff0f4a12537f7f0ad5d7afefb23d8c037c6ffc6af1583b2d805a346c6e13cfc8465de906e7d",
"rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f"
}
],
Expand Down
2 changes: 1 addition & 1 deletion test_vec/12/Poplar1_1.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"2c51ab72db13c851"
]
],
"public_share": "58a20d5e7eb4d586bf8c9c6a14e9e5265d7db6f9955cfea1fdae57cafbf001412abed2ad41e87ccb7df6eea8cdc5c6d35cebd1e8a163804e91f2f1280a61de836386feb9286f4ee02e32c5230f69e833b035e92ee3e6e1a471ae849d6a1cf7ac2afe6c06e0f0275b67ee6cb9f5d18c891bc463b7f13ff67a71e090ae40e69d60faf81cc33067e1add9f8a47ff0f4a12537f7f0ad5d7afefb23d8c037c6ffc6af1583b2d805a346c6e13cfc8465de906e7d",
"public_share": "58a20d5e7eb4d586bf8c9c6a14e9e5265dbed2ad41e87ccb7df6eea8cdc5c6d35c86feb9286f4ee02e32c5230f69e833b0fe6c06e0f0275b67ee6cb9f5d18c891b7db6f9955cfea1fdae57cafbf001412aebd1e8a163804e91f2f1280a61de836335e92ee3e6e1a471ae849d6a1cf7ac2ac463b7f13ff67a71e090ae40e69d60faf81cc33067e1add9f8a47ff0f4a12537f7f0ad5d7afefb23d8c037c6ffc6af1583b2d805a346c6e13cfc8465de906e7d",
"rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f"
}
],
Expand Down
2 changes: 1 addition & 1 deletion test_vec/12/Poplar1_2.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"339989fe65b198e6"
]
],
"public_share": "58a20d5e7eb4d586bf8c9c6a14e9e5265d7db6f9955cfea1fdae57cafbf001412abed2ad41e87ccb7df6eea8cdc5c6d35cebd1e8a163804e91f2f1280a61de836386feb9286f4ee02e32c5230f69e833b035e92ee3e6e1a471ae849d6a1cf7ac2afe6c06e0f0275b67ee6cb9f5d18c891bc463b7f13ff67a71e090ae40e69d60faf81cc33067e1add9f8a47ff0f4a12537f7f0ad5d7afefb23d8c037c6ffc6af1583b2d805a346c6e13cfc8465de906e7d",
"public_share": "58a20d5e7eb4d586bf8c9c6a14e9e5265dbed2ad41e87ccb7df6eea8cdc5c6d35c86feb9286f4ee02e32c5230f69e833b0fe6c06e0f0275b67ee6cb9f5d18c891b7db6f9955cfea1fdae57cafbf001412aebd1e8a163804e91f2f1280a61de836335e92ee3e6e1a471ae849d6a1cf7ac2ac463b7f13ff67a71e090ae40e69d60faf81cc33067e1add9f8a47ff0f4a12537f7f0ad5d7afefb23d8c037c6ffc6af1583b2d805a346c6e13cfc8465de906e7d",
"rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f"
}
],
Expand Down
2 changes: 1 addition & 1 deletion test_vec/12/Poplar1_3.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
"a35807f73caa5a74ae85ef7b22b4d0f0e0797662b6e830878683db51dae2630c"
]
],
"public_share": "58a20d5e7eb4d586bf8c9c6a14e9e5265d7db6f9955cfea1fdae57cafbf001412abed2ad41e87ccb7df6eea8cdc5c6d35cebd1e8a163804e91f2f1280a61de836386feb9286f4ee02e32c5230f69e833b035e92ee3e6e1a471ae849d6a1cf7ac2afe6c06e0f0275b67ee6cb9f5d18c891bc463b7f13ff67a71e090ae40e69d60faf81cc33067e1add9f8a47ff0f4a12537f7f0ad5d7afefb23d8c037c6ffc6af1583b2d805a346c6e13cfc8465de906e7d",
"public_share": "58a20d5e7eb4d586bf8c9c6a14e9e5265dbed2ad41e87ccb7df6eea8cdc5c6d35c86feb9286f4ee02e32c5230f69e833b0fe6c06e0f0275b67ee6cb9f5d18c891b7db6f9955cfea1fdae57cafbf001412aebd1e8a163804e91f2f1280a61de836335e92ee3e6e1a471ae849d6a1cf7ac2ac463b7f13ff67a71e090ae40e69d60faf81cc33067e1add9f8a47ff0f4a12537f7f0ad5d7afefb23d8c037c6ffc6af1583b2d805a346c6e13cfc8465de906e7d",
"rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f"
}
],
Expand Down

0 comments on commit cc87587

Please sign in to comment.