Skip to content

Commit ac563e7

Browse files
g11techGrapeBaBaunnawutsyjn99tcoratger
authored
aggregate all block signatures as naive list [devnet-1] (leanEthereum#67)
* aggregate all block siignatures * updated spec * update info * typo * improvs * further updates to forkchoice * improvs * apply spec call feedback * fix the proposer vote construction and consumption * enroll validators in state * fix some issues * fix the issue in code as well * feat: init aggregate all block signatures as naive list Signed-off-by: Chen Kai <281165273grape@gmail.com> * fix: fix state attestations processing Signed-off-by: Chen Kai <281165273grape@gmail.com> * fix: fix store process_block arg Signed-off-by: Chen Kai <281165273grape@gmail.com> * fix: fix store produce block Signed-off-by: Chen Kai <281165273grape@gmail.com> * fix: fix test_state Signed-off-by: Chen Kai <281165273grape@gmail.com> * feat: update to `SignedBlockAndVote` structure Signed-off-by: Chen Kai <281165273grape@gmail.com> * clean up proposer attestation data as not needed anymore * add clarification * removing redundancy in name to shorten it * add more clarification * fix: fix review comment Signed-off-by: Chen Kai <281165273grape@gmail.com> * fix: fix format Signed-off-by: Chen Kai <281165273grape@gmail.com> * fix: revert unexpected lint change Signed-off-by: Chen Kai <281165273grape@gmail.com> * fix: fix lint issue Signed-off-by: Chen Kai <281165273grape@gmail.com> * fix: revert test lint change Signed-off-by: Chen Kai <281165273grape@gmail.com> * fix: revert lint change Signed-off-by: Chen Kai <281165273grape@gmail.com> * fix: revert lint change Signed-off-by: Chen Kai <281165273grape@gmail.com> * Apply suggestion from @unnawut Co-authored-by: Unnawut Leepaisalsuwanna <921194+unnawut@users.noreply.github.com> * Apply suggestion from @unnawut Co-authored-by: Unnawut Leepaisalsuwanna <921194+unnawut@users.noreply.github.com> * fix: revert linter Signed-off-by: Chen Kai <281165273grape@gmail.com> * Update src/lean_spec/subspecs/containers/vote/vote.py Co-authored-by: Jun Song <87601811+syjn99@users.noreply.github.com> * fix: fix vote target Signed-off-by: Chen Kai <281165273grape@gmail.com> * update the produce block * ammed block proposal * Update src/lean_spec/subspecs/forkchoice/store.py Co-authored-by: g11tech <develop@g11tech.io> * Update src/lean_spec/subspecs/forkchoice/store.py Co-authored-by: g11tech <develop@g11tech.io> * fix: fix review comment Signed-off-by: Chen Kai <281165273grape@gmail.com> * Update src/lean_spec/subspecs/forkchoice/store.py Co-authored-by: g11tech <develop@g11tech.io> * fix; fix review comments Signed-off-by: Chen Kai <281165273grape@gmail.com> * fix: fix review comment Signed-off-by: Chen Kai <281165273grape@gmail.com> * fix: fix merge issue Signed-off-by: Chen Kai <281165273grape@gmail.com> * fix: fix review comment Signed-off-by: Chen Kai <281165273grape@gmail.com> * fix: fix review comments Signed-off-by: Chen Kai <281165273grape@gmail.com> * Update src/lean_spec/subspecs/containers/block/block.py Co-authored-by: Thomas Coratger <60488569+tcoratger@users.noreply.github.com> * Update src/lean_spec/subspecs/containers/attestation/attestation.py Co-authored-by: Thomas Coratger <60488569+tcoratger@users.noreply.github.com> * Update src/lean_spec/subspecs/containers/attestation/attestation.py Co-authored-by: Thomas Coratger <60488569+tcoratger@users.noreply.github.com> * fix: fix review comments Signed-off-by: Chen Kai <281165273grape@gmail.com> * fix: merge issue Signed-off-by: Chen Kai <281165273grape@gmail.com> * fix: revert Signed-off-by: Chen Kai <281165273grape@gmail.com> * fix: lint Signed-off-by: Chen Kai <281165273grape@gmail.com> * Update tests/lean_spec/subspecs/containers/test_state.py Co-authored-by: JihoonSong <jihoonsong@users.noreply.github.com> --------- Signed-off-by: Chen Kai <281165273grape@gmail.com> Co-authored-by: Chen Kai <281165273grape@gmail.com> Co-authored-by: Unnawut Leepaisalsuwanna <921194+unnawut@users.noreply.github.com> Co-authored-by: Jun Song <87601811+syjn99@users.noreply.github.com> Co-authored-by: Thomas Coratger <60488569+tcoratger@users.noreply.github.com> Co-authored-by: JihoonSong <jihoonsong@users.noreply.github.com>
1 parent 94109e4 commit ac563e7

28 files changed

Lines changed: 867 additions & 362 deletions
Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,41 @@
11
"""The container types for the Lean consensus specification."""
22

3-
from .block import Block, BlockBody, BlockHeader, SignedBlock
3+
from .attestation import (
4+
AggregatedAttestations,
5+
AggregatedSignatures,
6+
AggregationBits,
7+
Attestation,
8+
AttestationData,
9+
SignedAggregatedAttestations,
10+
SignedAttestation,
11+
)
12+
from .block import (
13+
Block,
14+
BlockBody,
15+
BlockHeader,
16+
BlockWithAttestation,
17+
SignedBlockWithAttestation,
18+
)
419
from .checkpoint import Checkpoint
520
from .config import Config
621
from .state import State
7-
from .vote import SignedVote, Vote
22+
from .validator import Validator
823

924
__all__ = [
25+
"AggregatedAttestations",
26+
"AggregatedSignatures",
27+
"AggregationBits",
28+
"AttestationData",
29+
"Attestation",
30+
"SignedAttestation",
31+
"SignedAggregatedAttestations",
1032
"Block",
33+
"BlockWithAttestation",
1134
"BlockBody",
1235
"BlockHeader",
1336
"Checkpoint",
1437
"Config",
15-
"SignedBlock",
16-
"SignedVote",
38+
"SignedBlockWithAttestation",
39+
"Validator",
1740
"State",
18-
"Vote",
1941
]
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
"""Attestation containers and related types for the Lean spec."""
2+
3+
from .attestation import (
4+
AggregatedAttestations,
5+
Attestation,
6+
AttestationData,
7+
SignedAggregatedAttestations,
8+
SignedAttestation,
9+
)
10+
from .types import AggregatedSignatures, AggregationBits
11+
12+
__all__ = [
13+
"AttestationData",
14+
"Attestation",
15+
"SignedAttestation",
16+
"SignedAggregatedAttestations",
17+
"AggregatedAttestations",
18+
"AggregatedSignatures",
19+
"AggregationBits",
20+
]
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"""Attestation-related container definitions."""
2+
3+
from lean_spec.subspecs.containers.slot import Slot
4+
from lean_spec.types import Bytes4000, Container, Uint64
5+
6+
from ..checkpoint import Checkpoint
7+
from .types import AggregatedSignatures, AggregationBits
8+
9+
10+
class AttestationData(Container):
11+
"""Attestation content describing the validator's observed chain view."""
12+
13+
slot: Slot
14+
"""The slot for which the attestation is made."""
15+
16+
head: Checkpoint
17+
"""The checkpoint representing the head block as observed by the validator."""
18+
19+
target: Checkpoint
20+
"""The checkpoint representing the target block as observed by the validator."""
21+
22+
source: Checkpoint
23+
"""The checkpoint representing the source block as observed by the validator."""
24+
25+
26+
class Attestation(Container):
27+
"""Validator specific attestation wrapping shared attestation data."""
28+
29+
validator_id: Uint64
30+
"""The index of the validator making the attestation."""
31+
32+
data: AttestationData
33+
"""The attestation data voted on by the validator."""
34+
35+
36+
class SignedAttestation(Container):
37+
"""Validator attestation bundled with its signature."""
38+
39+
message: Attestation
40+
"""The attestation message signed by the validator."""
41+
42+
signature: Bytes4000
43+
"""Signature aggregation produced by the leanVM (SNARKs in the future)."""
44+
45+
46+
class AggregatedAttestations(Container):
47+
"""Aggregated attestation consisting of participation bits and message."""
48+
49+
aggregation_bits: AggregationBits
50+
"""Bitfield indicating which validators participated in the aggregation."""
51+
52+
data: AttestationData
53+
"""Combined vote data similar to the beacon chain format.
54+
55+
Multiple validator votes are aggregated here without the complexity of
56+
committee assignments.
57+
"""
58+
59+
60+
class SignedAggregatedAttestations(Container):
61+
"""Aggregated attestation bundled with aggregated signatures."""
62+
63+
message: AggregatedAttestations
64+
"""Aggregated vote data."""
65+
66+
signature: AggregatedSignatures
67+
"""Aggregated vote plus its combined signature.
68+
69+
Stores a naive list of validator signatures that mirrors the attestation
70+
order.
71+
72+
TODO: this will be replaced by a SNARK in future devnets.
73+
"""
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"""Attestation-related SSZ types for the Lean consensus specification."""
2+
3+
from lean_spec.types import Bytes4000, SSZList
4+
from lean_spec.types.bitfields import BaseBitlist
5+
6+
from ...chain.config import VALIDATOR_REGISTRY_LIMIT
7+
8+
9+
class AggregationBits(BaseBitlist):
10+
"""Bitlist representing validator participation in an attestation."""
11+
12+
LIMIT = int(VALIDATOR_REGISTRY_LIMIT)
13+
14+
15+
class AggregatedSignatures(SSZList):
16+
"""Naive list of validator signatures used for aggregation placeholders."""
17+
18+
ELEMENT_TYPE = Bytes4000
19+
LIMIT = int(VALIDATOR_REGISTRY_LIMIT)
Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
"""Block containers and related types for the Lean Ethereum consensus specification."""
22

3-
from .block import Block, BlockBody, BlockHeader, SignedBlock
4-
from .types import Attestations
3+
from .block import (
4+
Block,
5+
BlockBody,
6+
BlockHeader,
7+
BlockWithAttestation,
8+
SignedBlockWithAttestation,
9+
)
10+
from .types import Attestations, BlockSignatures
511

612
__all__ = [
713
"Block",
814
"BlockBody",
915
"BlockHeader",
10-
"SignedBlock",
16+
"BlockWithAttestation",
17+
"SignedBlockWithAttestation",
1118
"Attestations",
19+
"BlockSignatures",
1220
]

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

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,18 @@
44
from lean_spec.types import Bytes32, Uint64
55
from lean_spec.types.container import Container
66

7-
from .types import Attestations
7+
from ..attestation import Attestation
8+
from .types import Attestations, BlockSignatures
89

910

1011
class BlockBody(Container):
1112
"""The body of a block, containing payload data."""
1213

1314
attestations: Attestations
14-
"""
15-
A list of votes included in the block.
15+
"""Plain validator attestations carried in the block body.
1616
17-
Note: This will eventually be replaced by aggregated attestations.
17+
Individual signatures live in the aggregated block signature list, so
18+
these entries contain only vote data without per-attestation signatures.
1819
"""
1920

2021

@@ -56,14 +57,30 @@ class Block(Container):
5657
"""The block's payload."""
5758

5859

59-
class SignedBlock(Container):
60-
"""A container for a block and the proposer's signature."""
60+
class BlockWithAttestation(Container):
61+
"""Bundle containing a block and the proposer's attestation."""
6162

62-
message: Block
63-
"""The block being signed."""
63+
block: Block
64+
"""The proposed block message."""
6465

65-
signature: Bytes32
66-
"""
67-
The proposer's signature of the block message.
68-
Note: Bytes32 is a placeholder; the actual signature is much larger.
66+
proposer_attestation: Attestation
67+
"""The proposer's vote corresponding to this block."""
68+
69+
70+
class SignedBlockWithAttestation(Container):
71+
"""Envelope carrying a block, proposer vote, and aggregated signatures."""
72+
73+
message: BlockWithAttestation
74+
"""The block plus proposer vote being signed."""
75+
76+
signature: BlockSignatures
77+
"""Aggregated signature payload for the block.
78+
79+
Signatures remain in attestation order followed by the proposer signature
80+
over entire message. For devnet 1, however the proposer signature is just
81+
over message.proposer_attestation since leanVM is not yet performant enough
82+
to aggregate signatures with sufficient throughput.
83+
84+
Eventually this field will be replaced by a SNARK (which represents the
85+
aggregation of all signatures).
6986
"""
Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
"""Block-specific SSZ types for the Lean Ethereum consensus specification."""
22

3-
from lean_spec.types import SSZList
3+
from lean_spec.types import Bytes4000, SSZList
44

55
from ...chain.config import VALIDATOR_REGISTRY_LIMIT
6-
from ..vote import SignedVote
6+
from ..attestation import Attestation
77

88

99
class Attestations(SSZList):
10-
"""List of signed votes (attestations) included in a block."""
10+
"""List of validator attestations included in a block."""
1111

12-
ELEMENT_TYPE = SignedVote
12+
ELEMENT_TYPE = Attestation
13+
LIMIT = int(VALIDATOR_REGISTRY_LIMIT)
14+
15+
16+
class BlockSignatures(SSZList):
17+
"""Aggregated signature list included alongside the block."""
18+
19+
ELEMENT_TYPE = Bytes4000
1320
LIMIT = int(VALIDATOR_REGISTRY_LIMIT)

src/lean_spec/subspecs/containers/checkpoint.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
"""Checkpoint Container."""
22

3+
from typing import Self
4+
35
from lean_spec.subspecs.containers.slot import Slot
46
from lean_spec.types import Bytes32
57
from lean_spec.types.container import Container
@@ -13,3 +15,8 @@ class Checkpoint(Container):
1315

1416
slot: Slot
1517
"""The slot number of the checkpoint's block."""
18+
19+
@classmethod
20+
def default(cls) -> Self:
21+
"""Return a default checkpoint."""
22+
return cls(root=Bytes32.zero(), slot=Slot(0))

src/lean_spec/subspecs/containers/state/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
JustificationRoots,
77
JustificationValidators,
88
JustifiedSlots,
9+
Validators,
910
)
1011

1112
__all__ = [
@@ -14,4 +15,5 @@
1415
"JustificationRoots",
1516
"JustificationValidators",
1617
"JustifiedSlots",
18+
"Validators",
1719
]

src/lean_spec/subspecs/containers/state/state.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,17 @@
1313
is_proposer,
1414
)
1515

16-
from ..block import Block, BlockBody, BlockHeader, SignedBlock
16+
from ..block import Block, BlockBody, BlockHeader
1717
from ..block.types import Attestations
1818
from ..checkpoint import Checkpoint
1919
from ..config import Config
2020
from ..slot import Slot
21-
from ..vote import Vote
2221
from .types import (
2322
HistoricalBlockHashes,
2423
JustificationRoots,
2524
JustificationValidators,
2625
JustifiedSlots,
26+
Validators,
2727
)
2828

2929

@@ -55,6 +55,9 @@ class State(Container):
5555
justified_slots: JustifiedSlots
5656
"""A bitfield indicating which historical slots were justified."""
5757

58+
validators: Validators
59+
"""Registry of validators tracked by the state."""
60+
5861
# Justification tracking (flattened for SSZ compatibility)
5962
justifications_roots: JustificationRoots
6063
"""Roots of justified blocks."""
@@ -99,10 +102,11 @@ def generate_genesis(cls, genesis_time: Uint64, num_validators: Uint64) -> "Stat
99102
config=genesis_config,
100103
slot=Slot(0),
101104
latest_block_header=genesis_header,
102-
latest_justified=Checkpoint(root=Bytes32.zero(), slot=Slot(0)),
103-
latest_finalized=Checkpoint(root=Bytes32.zero(), slot=Slot(0)),
105+
latest_justified=Checkpoint.default(),
106+
latest_finalized=Checkpoint.default(),
104107
historical_block_hashes=HistoricalBlockHashes(data=[]),
105108
justified_slots=JustifiedSlots(data=[]),
109+
validators=Validators(data=[]),
106110
justifications_roots=JustificationRoots(data=[]),
107111
justifications_validators=JustificationValidators(data=[]),
108112
)
@@ -429,8 +433,8 @@ def process_attestations(
429433
latest_finalized = self.latest_finalized
430434

431435
# Process each attestation in the block.
432-
for signed_vote in attestations:
433-
vote: Vote = signed_vote.data
436+
for attestation in attestations:
437+
vote = attestation.data
434438
source = vote.source
435439
target = vote.target
436440

@@ -484,9 +488,9 @@ def process_attestations(
484488
}
485489
)
486490

487-
def state_transition(self, signed_block: SignedBlock, valid_signatures: bool = True) -> "State":
491+
def state_transition(self, block: Block, valid_signatures: bool = True) -> "State":
488492
"""
489-
Apply the complete state transition function for a signed block.
493+
Apply the complete state transition function for a block.
490494
491495
This method represents the full state transition function:
492496
1. Validate signatures if required
@@ -496,8 +500,8 @@ def state_transition(self, signed_block: SignedBlock, valid_signatures: bool = T
496500
497501
Parameters
498502
----------
499-
signed_block : SignedBlock
500-
The signed block to apply to the state.
503+
block : Block
504+
The block to apply to the state.
501505
valid_signatures : bool, optional
502506
Whether to validate block signatures. Defaults to True.
503507
@@ -515,8 +519,6 @@ def state_transition(self, signed_block: SignedBlock, valid_signatures: bool = T
515519
if not valid_signatures:
516520
raise AssertionError("Block signatures must be valid")
517521

518-
block = signed_block.message
519-
520522
# First, process any intermediate slots.
521523
state = self.process_slots(block.slot)
522524

0 commit comments

Comments
 (0)