Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added verification to certificate #82

Merged
merged 4 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 22 additions & 4 deletions da/common.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from dataclasses import dataclass
from itertools import chain, zip_longest
from typing import List, Generator, Self


from hashlib import sha3_256
from itertools import chain, zip_longest, compress
from typing import List, Generator, Self, Sequence

from eth2spec.eip7594.mainnet import Bytes32, KZGCommitment as Commitment
from py_ecc.bls import G2ProofOfPossession as bls_pop


class NodeId(Bytes32):
Expand Down Expand Up @@ -55,3 +55,21 @@ class Certificate:
aggregated_column_commitment: Commitment
row_commitments: List[Commitment]

def verify(self, nodes_public_keys: List[BLSPublickey]) -> bool:
"""
List of nodes public keys should be a trusted list of verified proof of possession keys.
Otherwise, we could fall under the Rogue Key Attack
`assert all(bls_pop.PopVerify(pk, proof) for pk, proof in zip(node_public_keys, pops))`
"""
# we sort them as the signers bitfield is sorted by the public keys as well
signers_keys = list(compress(sorted(nodes_public_keys), self.signers))
message = build_attestation_message(self.aggregated_column_commitment, self.row_commitments)
return bls_pop.AggregateVerify(signers_keys, [message]*len(signers_keys), self.aggregated_signatures)
Comment on lines +58 to +67
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davidrusu I added this comment. This keys verification should be done upon registration.
@megonen We have to update the specification documents with this most probably.



def build_attestation_message(aggregated_column_commitment: Commitment, row_commitments: Sequence[Commitment]) -> bytes:
hasher = sha3_256()
hasher.update(bytes(aggregated_column_commitment))
for c in row_commitments:
hasher.update(bytes(c))
return hasher.digest()
12 changes: 4 additions & 8 deletions da/dispersal.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from py_ecc.bls import G2ProofOfPossession as bls_pop

from da.common import Certificate, NodeId, BLSPublickey, Bitfield
from da.common import Certificate, NodeId, BLSPublickey, Bitfield, build_attestation_message
from da.encoder import EncodedData
from da.verifier import DABlob, Attestation

Expand All @@ -19,9 +19,9 @@ class DispersalSettings:
class Dispersal:
def __init__(self, settings: DispersalSettings):
self.settings = settings
# sort nodes_ids and related public keys
# sort over public keys
self.settings.nodes_ids, self.settings.nodes_pubkey = zip(
*sorted(zip(self.settings.nodes_ids, self.settings.nodes_pubkey), key=lambda x: x[0])
*sorted(zip(self.settings.nodes_ids, self.settings.nodes_pubkey), key=lambda x: x[1])
)

def _prepare_data(self, encoded_data: EncodedData) -> Generator[DABlob, None, None]:
Expand Down Expand Up @@ -71,11 +71,7 @@ def _verify_attestation(public_key: BLSPublickey, attested_message: bytes, attes

@staticmethod
def _build_attestation_message(encoded_data: EncodedData) -> bytes:
hasher = sha3_256()
hasher.update(bytes(encoded_data.aggregated_column_commitment))
for c in encoded_data.row_commitments:
hasher.update(bytes(c))
return hasher.digest()
return build_attestation_message(encoded_data.aggregated_column_commitment, encoded_data.row_commitments)

def disperse(self, encoded_data: EncodedData) -> Optional[Certificate]:
attestations = []
Expand Down
18 changes: 6 additions & 12 deletions da/test_dispersal.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
from hashlib import sha3_256
from unittest import TestCase

from .encoder import DAEncoderParams, DAEncoder
from .test_encoder import TestEncoder

from da.encoder import DAEncoderParams, DAEncoder
from da.test_encoder import TestEncoder
from da.verifier import DAVerifier, DABlob
from da.common import NodeId, Attestation, Bitfield
from da.dispersal import Dispersal, EncodedData, DispersalSettings
from py_ecc.bls import G2ProofOfPossession as bls_pop

from .verifier import DAVerifier, DABlob
from py_ecc.bls import G2ProofOfPossession as bls_pop


class TestDispersal(TestCase):
Expand Down Expand Up @@ -46,7 +45,7 @@ def test_build_certificate_enough_attestations(self):
self.assertEqual(certificate.row_commitments, [])
self.assertIsNotNone(certificate.aggregated_signatures)
self.assertTrue(
bls_pop.AggregateVerify(self.public_keys, [mock_message]*len(self.public_keys), certificate.aggregated_signatures)
certificate.verify(self.public_keys)
)

def test_disperse(self):
Expand All @@ -64,12 +63,7 @@ def __send_and_await_response(node: NodeId, blob: DABlob):

certificate = self.dispersal.disperse(encoded_data)
self.assertIsNotNone(certificate)
self.assertTrue(
bls_pop.AggregateVerify(
self.public_keys[:self.dispersal.settings.threshold],
[self.dispersal._build_attestation_message(encoded_data)]*self.dispersal.settings.threshold,
certificate.aggregated_signatures
)
self.assertTrue(certificate.verify(self.public_keys)
)
self.assertEqual(
certificate.signers,
Expand Down