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

Verified

This commit was signed with the committer’s verified signature.
natesales Nate Sales
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.