Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(side-dag): update APIs
Browse files Browse the repository at this point in the history
glevco committed Jun 20, 2024
1 parent 0c60081 commit fcab293
Showing 6 changed files with 49 additions and 14 deletions.
4 changes: 4 additions & 0 deletions hathor/conf/settings.py
Original file line number Diff line number Diff line change
@@ -440,6 +440,10 @@ def GENESIS_TX2_TIMESTAMP(self) -> int:
# The consensus algorithm protocol settings.
CONSENSUS_ALGORITHM: ConsensusSettings = PowSettings()

# The name and symbol of the native token. This is only used in APIs to serve clients.
NATIVE_TOKEN_NAME: str = 'Hathor'
NATIVE_TOKEN_SYMBOL: str = 'HTR'

@classmethod
def from_yaml(cls, *, filepath: str) -> 'HathorSettings':
"""Takes a filepath to a yaml file and returns a validated HathorSettings instance."""
2 changes: 2 additions & 0 deletions hathor/consensus/poa/__init__.py
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
SIGNER_ID_LEN,
calculate_weight,
get_hashed_poa_data,
get_signer_index_and_public_key,
is_in_turn,
)
from .poa_block_producer import PoaBlockProducer
@@ -19,4 +20,5 @@
'PoaBlockProducer',
'PoaSigner',
'PoaSignerFile',
'get_signer_index_and_public_key',
]
12 changes: 12 additions & 0 deletions hathor/consensus/poa/poa.py
Original file line number Diff line number Diff line change
@@ -46,3 +46,15 @@ def calculate_weight(settings: PoaSettings, block: PoaBlock, signer_index: int)
"""Return the weight for the given block and signer."""
is_in_turn_flag = is_in_turn(settings=settings, height=block.get_height(), signer_index=signer_index)
return BLOCK_WEIGHT_IN_TURN if is_in_turn_flag else BLOCK_WEIGHT_OUT_OF_TURN


def get_signer_index_and_public_key(settings: PoaSettings, signer_id: bytes) -> tuple[int, bytes] | None:
"""Given a `signer_id`, return its signer index and public key bytes. Return `None` if not found."""
from hathor.consensus.poa import PoaSigner
sorted_signers = sorted(settings.signers)

for i, public_key_bytes in enumerate(sorted_signers):
if signer_id == PoaSigner.get_poa_signer_id(public_key_bytes):
return i, public_key_bytes

return None
21 changes: 21 additions & 0 deletions hathor/transaction/poa/poa_block.py
Original file line number Diff line number Diff line change
@@ -12,7 +12,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Any

from typing_extensions import override

from hathor.consensus import poa
from hathor.consensus.consensus_settings import PoaSettings
from hathor.transaction import Block, TxOutput, TxVersion
from hathor.transaction.storage import TransactionStorage
from hathor.transaction.util import VerboseCallback, int_to_bytes, unpack, unpack_len
@@ -53,6 +58,7 @@ def __init__(
self.signer_id = signer_id
self.signature = signature

@override
def get_graph_fields_from_struct(self, buf: bytes, *, verbose: VerboseCallback = None) -> bytes:
buf = super().get_graph_fields_from_struct(buf, verbose=verbose)

@@ -73,8 +79,23 @@ def get_graph_fields_from_struct(self, buf: bytes, *, verbose: VerboseCallback =

return buf

@override
def get_graph_struct(self) -> bytes:
assert len(self.signer_id) == poa.SIGNER_ID_LEN
struct_bytes_without_poa = super().get_graph_struct()
signature_len = int_to_bytes(len(self.signature), 1)
return struct_bytes_without_poa + self.signer_id + signature_len + self.signature

@override
def to_json(self, decode_script: bool = False, include_metadata: bool = False) -> dict[str, Any]:
poa_settings = self._settings.CONSENSUS_ALGORITHM
assert isinstance(poa_settings, PoaSettings)
json = super().to_json(decode_script=decode_script, include_metadata=include_metadata)
index_and_key = poa.get_signer_index_and_public_key(poa_settings, self.signer_id)

if index_and_key is not None:
_, signer = index_and_key
json['signer'] = signer.hex()

json['signer_id'] = self.signer_id.hex()
return json
19 changes: 5 additions & 14 deletions hathor/verification/poa_block_verifier.py
Original file line number Diff line number Diff line change
@@ -19,7 +19,6 @@
from hathor.conf.settings import HathorSettings
from hathor.consensus import poa
from hathor.consensus.consensus_settings import PoaSettings
from hathor.consensus.poa.poa_signer import PoaSigner
from hathor.crypto.util import get_public_key_from_bytes_compressed
from hathor.transaction.exceptions import PoaValidationError
from hathor.transaction.poa import PoaBlock
@@ -41,17 +40,13 @@ def verify_poa(self, block: PoaBlock) -> None:
raise PoaValidationError('blocks must not have rewards in a PoA network')

# validate that the signature is valid
sorted_signers = sorted(poa_settings.signers)
signer_index: int | None = None

for i, public_key_bytes in enumerate(sorted_signers):
if self._verify_poa_signature(block, public_key_bytes):
signer_index = i
break

if signer_index is None:
signer = poa.get_signer_index_and_public_key(poa_settings, block.signer_id)
if signer is None:
raise PoaValidationError('invalid PoA signature')

signer_index, public_key_bytes = signer
self._verify_poa_signature(block, public_key_bytes)

# validate block weight is in turn
expected_weight = poa.calculate_weight(poa_settings, block, signer_index)
if block.weight != expected_weight:
@@ -60,10 +55,6 @@ def verify_poa(self, block: PoaBlock) -> None:
@staticmethod
def _verify_poa_signature(block: PoaBlock, public_key_bytes: bytes) -> bool:
"""Return whether the provided public key was used to sign the block Proof-of-Authority."""
signer_id = PoaSigner.get_poa_signer_id(public_key_bytes)
if block.signer_id != signer_id:
return False

public_key = get_public_key_from_bytes_compressed(public_key_bytes)
hashed_poa_data = poa.get_hashed_poa_data(block)
try:
5 changes: 5 additions & 0 deletions hathor/version_resource.py
Original file line number Diff line number Diff line change
@@ -51,6 +51,11 @@ def render_GET(self, request):
'reward_spend_min_blocks': self._settings.REWARD_SPEND_MIN_BLOCKS,
'max_number_inputs': self._settings.MAX_NUM_INPUTS,
'max_number_outputs': self._settings.MAX_NUM_OUTPUTS,
'decimal_places': self._settings.DECIMAL_PLACES,
'native_token': dict(
name=self._settings.NATIVE_TOKEN_NAME,
symbol=self._settings.NATIVE_TOKEN_SYMBOL,
),
}
return json_dumpb(data)

0 comments on commit fcab293

Please sign in to comment.