Skip to content

refactor: public key class #169

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

Merged
merged 2 commits into from
Apr 23, 2025
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
18 changes: 12 additions & 6 deletions crypto/identity/public_key.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
from binascii import hexlify, unhexlify

from coincurve import PublicKey as PubKey

from crypto.identity.private_key import PrivateKey

class PublicKey(object):
public_key: str

def __init__(self, public_key: str):
self.public_key = PubKey(unhexlify(public_key.encode()))
self.public_key = public_key

@classmethod
def from_passphrase(cls, passphrase: str) -> str:
def from_passphrase(cls, passphrase: str) -> 'PublicKey':
private_key = PrivateKey.from_passphrase(passphrase)

return private_key.public_key
return cls(private_key.public_key)

@classmethod
def from_hex(cls, public_key):
def from_hex(cls, public_key) -> 'PublicKey':
return cls(public_key)

@classmethod
def recover(cls, message: bytes, signature: bytes) -> 'PublicKey':
recovered_public_key = PubKey.from_signature_and_message(signature, message, hasher=None)

return cls(recovered_public_key.format().hex())
2 changes: 1 addition & 1 deletion crypto/transactions/builder/evm_call_builder.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from crypto.transactions.builder.base import AbstractTransactionBuilder
from crypto.transactions.builder.abstract_transaction_builder import AbstractTransactionBuilder
from crypto.transactions.types.evm_call import EvmCall
from crypto.utils.transaction_utils import TransactionUtils

Expand Down
2 changes: 1 addition & 1 deletion crypto/transactions/builder/multipayment_builder.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from crypto.enums.contract_addresses import ContractAddresses
from crypto.transactions.builder.base import AbstractTransactionBuilder
from crypto.transactions.builder.abstract_transaction_builder import AbstractTransactionBuilder
from crypto.transactions.types.multipayment import Multipayment

class MultipaymentBuilder(AbstractTransactionBuilder):
Expand Down
2 changes: 1 addition & 1 deletion crypto/transactions/builder/transfer_builder.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from crypto.transactions.builder.base import AbstractTransactionBuilder
from crypto.transactions.builder.abstract_transaction_builder import AbstractTransactionBuilder
from crypto.transactions.types.transfer import Transfer


Expand Down
2 changes: 1 addition & 1 deletion crypto/transactions/builder/unvote_builder.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from crypto.enums.contract_addresses import ContractAddresses
from crypto.transactions.builder.base import AbstractTransactionBuilder
from crypto.transactions.builder.abstract_transaction_builder import AbstractTransactionBuilder
from crypto.transactions.types.unvote import Unvote

class UnvoteBuilder(AbstractTransactionBuilder):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import re
from crypto.enums.contract_addresses import ContractAddresses
from crypto.exceptions import InvalidUsernameException
from crypto.transactions.builder.base import AbstractTransactionBuilder
from crypto.transactions.builder.abstract_transaction_builder import AbstractTransactionBuilder
from crypto.transactions.types.username_registration import UsernameRegistration

class UsernameRegistrationBuilder(AbstractTransactionBuilder):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from crypto.enums.contract_addresses import ContractAddresses
from crypto.transactions.builder.base import AbstractTransactionBuilder
from crypto.transactions.builder.abstract_transaction_builder import AbstractTransactionBuilder
from crypto.transactions.types.username_resignation import UsernameResignation

class UsernameResignationBuilder(AbstractTransactionBuilder):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from crypto.enums.contract_addresses import ContractAddresses
from crypto.transactions.builder.base import AbstractTransactionBuilder
from crypto.transactions.builder.abstract_transaction_builder import AbstractTransactionBuilder
from crypto.transactions.types.validator_registration import ValidatorRegistration

class ValidatorRegistrationBuilder(AbstractTransactionBuilder):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from crypto.enums.contract_addresses import ContractAddresses
from crypto.transactions.builder.base import AbstractTransactionBuilder
from crypto.transactions.builder.abstract_transaction_builder import AbstractTransactionBuilder
from crypto.transactions.types.validator_resignation import ValidatorResignation

class ValidatorResignationBuilder(AbstractTransactionBuilder):
Expand Down
2 changes: 1 addition & 1 deletion crypto/transactions/builder/vote_builder.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from crypto.enums.contract_addresses import ContractAddresses
from crypto.transactions.builder.base import AbstractTransactionBuilder
from crypto.transactions.builder.abstract_transaction_builder import AbstractTransactionBuilder
from crypto.transactions.types.vote import Vote

class VoteBuilder(AbstractTransactionBuilder):
Expand Down
20 changes: 8 additions & 12 deletions crypto/transactions/types/abstract_transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
from crypto.enums.contract_abi_type import ContractAbiType
from crypto.identity.address import Address
from crypto.identity.private_key import PrivateKey
from crypto.identity.public_key import PublicKey
from crypto.utils.transaction_utils import TransactionUtils
from coincurve import PublicKey

class AbstractTransaction:
def __init__(self, data: dict):
Expand Down Expand Up @@ -35,19 +35,14 @@ def sign(self, private_key: PrivateKey):

return self

def get_public_key(self, compact_signature, hash_):
public_key = PublicKey.from_signature_and_message(compact_signature, hash_, hasher=None)

return public_key

def recover_sender(self):
signature_with_recid = self._get_signature()
if not signature_with_recid:
return False

hash_ = bytes.fromhex(self.hash(skip_signature=True))
public_key = self.get_public_key(signature_with_recid, hash_)
self.data['senderPublicKey'] = public_key.format().hex()
public_key = self.__recover_public_key(signature_with_recid, hash_)
self.data['senderPublicKey'] = public_key.public_key
self.data['senderAddress'] = Address.from_public_key(self.data['senderPublicKey'])

def verify(self) -> bool:
Expand All @@ -56,14 +51,12 @@ def verify(self) -> bool:
return False

hash_ = bytes.fromhex(self.hash(skip_signature=True))
recovered_public_key = self.get_public_key(signature_with_recid, hash_)
recovered_public_key = self.__recover_public_key(signature_with_recid, hash_)
sender_public_key_hex = self.data.get('senderPublicKey')
if not sender_public_key_hex:
return False

sender_public_key_bytes = bytes.fromhex(sender_public_key_hex)

return recovered_public_key.format() == sender_public_key_bytes
return recovered_public_key.public_key == sender_public_key_hex

def serialize(self, skip_signature: bool = False) -> bytes:
from crypto.transactions.serializer import Serializer
Expand Down Expand Up @@ -94,3 +87,6 @@ def _decode_payload(data: dict, abi_type: ContractAbiType = ContractAbiType.CONS
from crypto.transactions.deserializer import Deserializer

return Deserializer.decode_payload(data, abi_type)

def __recover_public_key(self, compact_signature, hash_):
return PublicKey.recover(hash_, compact_signature)
6 changes: 3 additions & 3 deletions crypto/utils/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
from typing import Union

from Cryptodome.Hash import keccak
from coincurve import PublicKey

from crypto.identity.private_key import PrivateKey
from crypto.identity.public_key import PublicKey

class Message(object):
public_key: bytes
Expand Down Expand Up @@ -79,9 +79,9 @@ def verify(self):

signature = signature_r + signature_s + bytes([signature_v - 27])

public_key = PublicKey.from_signature_and_message(signature, message_hash, hasher=None)
public_key = PublicKey.recover(message_hash, signature)

return public_key.format() == unhexlify(self.public_key)
return public_key.public_key == unhexlify(self.public_key).hex()

def to_dict(self):
"""Return a dictionary of the message
Expand Down
7 changes: 2 additions & 5 deletions tests/identity/test_public_key.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
from binascii import hexlify
from crypto.identity.public_key import PublicKey


def test_public_key_from_passphrase(identity):
public_key = PublicKey.from_passphrase(identity['passphrase'])
assert public_key == identity['data']['public_key']
assert public_key.public_key == identity['data']['public_key']


def test_public_key_from_hex(identity):
public_key = PublicKey.from_hex(identity['data']['public_key'])
assert isinstance(public_key, PublicKey)

public_key_hex = hexlify(public_key.public_key.format()).decode()

assert public_key_hex == identity['data']['public_key']
assert public_key.public_key == identity['data']['public_key']