Skip to content

Commit 60768dd

Browse files
authored
xmss: full ssz serialization (#210)
* xmss: full ssz serialization * some fixes * some fixes * add todos * cleanup * fix test
1 parent 10c1ef5 commit 60768dd

17 files changed

Lines changed: 274 additions & 626 deletions

File tree

packages/testing/src/consensus_testing/keys.py

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
from typing import NamedTuple, Optional
44

5-
from lean_spec.subspecs.containers import Attestation, Signature
5+
from lean_spec.subspecs.containers import Attestation
66
from lean_spec.subspecs.containers.slot import Slot
77
from lean_spec.subspecs.ssz.hash import hash_tree_root
8-
from lean_spec.subspecs.xmss.containers import PublicKey, SecretKey
8+
from lean_spec.subspecs.xmss.containers import PublicKey, SecretKey, Signature
99
from lean_spec.subspecs.xmss.interface import (
1010
TEST_SIGNATURE_SCHEME,
1111
GeneralizedXmssScheme,
@@ -174,19 +174,8 @@ def sign_attestation(self, attestation: Attestation) -> Signature:
174174
# This produces a cryptographic hash of the entire attestation structure.
175175
message = bytes(hash_tree_root(attestation))
176176

177-
# Generate the XMSS signature using the validator's (now prepared) secret key.
178-
xmss_sig = self.scheme.sign(sk, epoch, message)
179-
180-
# Convert the signature to the wire format (byte array).
181-
signature_bytes = xmss_sig.to_bytes(self.scheme.config)
182-
183-
# Ensure the signature meets the consensus spec length (3116 bytes).
184-
#
185-
# This is necessary when using TEST_CONFIG (796 bytes) vs PROD_CONFIG.
186-
# Padding with zeros on the right maintains compatibility.
187-
padded_bytes = signature_bytes.ljust(Signature.LENGTH, b"\x00")
188-
189-
return Signature(padded_bytes)
177+
# Generate and return the XMSS signature using the validator's (now prepared) secret key.
178+
return self.scheme.sign(sk, epoch, message)
190179

191180
def get_public_key(self, validator_index: ValidatorIndex) -> PublicKey:
192181
"""

packages/testing/src/consensus_testing/test_fixtures/fork_choice.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from pydantic import model_validator
99

1010
from lean_spec.subspecs.chain.config import SECONDS_PER_SLOT
11-
from lean_spec.subspecs.containers import Signature
1211
from lean_spec.subspecs.containers.attestation import (
1312
Attestation,
1413
AttestationData,
@@ -26,7 +25,15 @@
2625
from lean_spec.subspecs.containers.state import Validators
2726
from lean_spec.subspecs.containers.state.state import State
2827
from lean_spec.subspecs.forkchoice import Store
28+
from lean_spec.subspecs.koalabear import Fp
2929
from lean_spec.subspecs.ssz import hash_tree_root
30+
from lean_spec.subspecs.xmss.constants import PROD_CONFIG
31+
from lean_spec.subspecs.xmss.containers import (
32+
HashDigestList,
33+
HashTreeOpening,
34+
Randomness,
35+
Signature,
36+
)
3037
from lean_spec.subspecs.xmss.interface import TEST_SIGNATURE_SCHEME
3138
from lean_spec.types import Bytes32, Uint64, ValidatorIndex
3239

@@ -192,11 +199,7 @@ def make_fixture(self) -> ForkChoiceTest:
192199
# Update validator pubkeys to match key_manager's generated keys
193200
updated_validators = [
194201
validator.model_copy(
195-
update={
196-
"pubkey": key_manager[ValidatorIndex(i)].public.to_bytes(
197-
key_manager.scheme.config
198-
)
199-
}
202+
update={"pubkey": key_manager[ValidatorIndex(i)].public.encode_bytes()}
200203
)
201204
for i, validator in enumerate(self.anchor_state.validators)
202205
]
@@ -481,5 +484,13 @@ def _build_signed_attestation_from_spec(
481484
# Create signed attestation
482485
return SignedAttestation(
483486
message=attestation,
484-
signature=spec.signature if spec.signature is not None else Signature.zero(),
487+
signature=(
488+
spec.signature
489+
if spec.signature is not None
490+
else Signature(
491+
path=HashTreeOpening(siblings=HashDigestList(data=[])),
492+
rho=Randomness(data=[Fp(0) for _ in range(PROD_CONFIG.RAND_LEN_FE)]),
493+
hashes=HashDigestList(data=[]),
494+
)
495+
),
485496
)

packages/testing/src/consensus_testing/test_types/signed_attestation_spec.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Lightweight attestation specification for test definitions."""
22

3-
from lean_spec.subspecs.containers.signature import Signature
43
from lean_spec.subspecs.containers.slot import Slot
4+
from lean_spec.subspecs.xmss.containers import Signature
55
from lean_spec.types import CamelModel, Uint64, ValidatorIndex
66

77

@@ -33,5 +33,5 @@ class SignedAttestationSpec(CamelModel):
3333
"""
3434
The signature for the attestation.
3535
36-
If None, uses Signature.zero() for testing.
36+
If None, uses an empty signature for testing.
3737
"""

src/lean_spec/subspecs/containers/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
)
2727
from .checkpoint import Checkpoint
2828
from .config import Config
29-
from .signature import Signature
3029
from .state import State
3130
from .validator import Validator
3231

@@ -45,7 +44,6 @@
4544
"Checkpoint",
4645
"Config",
4746
"SignedBlockWithAttestation",
48-
"Signature",
4947
"Validator",
5048
"State",
5149
]

src/lean_spec/subspecs/containers/attestation/attestation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
from lean_spec.subspecs.containers.slot import Slot
1616
from lean_spec.types import Container, Uint64
1717

18+
from ...xmss.containers import Signature
1819
from ..checkpoint import Checkpoint
19-
from ..signature import Signature
2020
from .types import AggregatedSignatures, AggregationBits
2121

2222

src/lean_spec/subspecs/containers/attestation/types.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from lean_spec.types.bitfields import BaseBitlist
55

66
from ...chain.config import VALIDATOR_REGISTRY_LIMIT
7-
from ..signature import Signature
7+
from ...xmss.containers import Signature
88

99

1010
class AggregationBits(BaseBitlist):

src/lean_spec/subspecs/containers/block/types.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
from lean_spec.types import SSZList
44

55
from ...chain.config import VALIDATOR_REGISTRY_LIMIT
6+
from ...xmss.containers import Signature
67
from ..attestation import Attestation
7-
from ..signature import Signature
88

99

1010
class Attestations(SSZList):

src/lean_spec/subspecs/containers/signature.py

Lines changed: 0 additions & 30 deletions
This file was deleted.

src/lean_spec/subspecs/containers/validator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class Validator(Container):
2020

2121
def get_pubkey(self, scheme: GeneralizedXmssScheme = TEST_SIGNATURE_SCHEME) -> PublicKey:
2222
"""Get the XMSS public key from this validator."""
23-
return PublicKey.from_bytes(bytes(self.pubkey), scheme.config)
23+
return PublicKey.decode_bytes(bytes(self.pubkey))
2424

2525
def produce_attestation(self, data: AttestationData) -> Attestation:
2626
"""

src/lean_spec/subspecs/forkchoice/store.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@
2828
BlockBody,
2929
Checkpoint,
3030
Config,
31-
Signature,
3231
SignedAttestation,
3332
SignedBlockWithAttestation,
3433
State,
3534
)
3635
from lean_spec.subspecs.containers.block import Attestations
3736
from lean_spec.subspecs.containers.slot import Slot
3837
from lean_spec.subspecs.ssz.hash import hash_tree_root
38+
from lean_spec.subspecs.xmss.containers import Signature
3939
from lean_spec.types import (
4040
ZERO_HASH,
4141
Bytes32,

0 commit comments

Comments
 (0)