diff --git a/test/python/test_instructions.py b/test/python/test_instructions.py index 253a0da3..7e5c58f0 100644 --- a/test/python/test_instructions.py +++ b/test/python/test_instructions.py @@ -16,6 +16,7 @@ from utils.message import ( Preattestation, Attestation, + AttestationDal, Fitness, BlockHeader, Block @@ -397,6 +398,52 @@ def test_sign_attestation( account.check_signature(signature, bytes(attestation)) +@pytest.mark.parametrize("account", [DEFAULT_ACCOUNT]) +@pytest.mark.parametrize("with_hash", [False, True]) +def test_sign_attestation_dal( + account: Account, + with_hash: bool, + client: TezosClient, + firmware: Firmware, + navigator: Navigator) -> None: + """Test the SIGN(_WITH_HASH) instruction on attestation.""" + + main_chain_id: int = 0 + main_hwm = Hwm(0) + test_hwm = Hwm(0) + + instructions = get_setup_app_context_instructions(firmware) + + send_and_navigate( + send=lambda: client.setup_app_context( + account, + main_chain_id, + main_hwm, + test_hwm), + navigate=lambda: navigator.navigate(instructions)) + + attestation = AttestationDal( + chain_id=main_chain_id, + branch="0000000000000000000000000000000000000000000000000000000000000000", + slot=0, + op_level=0, + op_round=0, + block_payload_hash="0000000000000000000000000000000000000000000000000000000000000000", + dal_message="000000000000000000000000000000000000000000000000000000000000000000000000000" + ) + + if with_hash: + signature = client.sign_message(account, attestation) + account.check_signature(signature, bytes(attestation)) + else: + attestation_hash, signature = client.sign_message_with_hash(account, attestation) + assert attestation_hash == attestation.hash, \ + f"Expected hash {attestation.hash.hex()} but got {attestation_hash.hex()}" + account.check_signature(signature, bytes(attestation)) + + + + @pytest.mark.parametrize("account", [DEFAULT_ACCOUNT]) @pytest.mark.parametrize("with_hash", [False, True]) def test_sign_block( diff --git a/test/python/utils/message.py b/test/python/utils/message.py index 69c10d22..341f1acd 100644 --- a/test/python/utils/message.py +++ b/test/python/utils/message.py @@ -81,18 +81,19 @@ class ConsensusProtocol(IntEnum): class OperationTag(IntEnum): """Class representing the operation tag.""" - PROPOSAL = 5 - BALLOT = 6 - BABYLON_REVEAL = 107 - BABYLON_TRANSACTION = 108 - BABYLON_ORIGINATION = 109 - BABYLON_DELEGATION = 110 - ATHENS_REVEAL = 7 - ATHENS_TRANSACTION = 8 - ATHENS_ORIGINATION = 9 - ATHENS_DELEGATION = 10 - PREATTESTATION = 20 - ATTESTATION = 21 + PROPOSAL = 5 + BALLOT = 6 + BABYLON_REVEAL = 107 + BABYLON_TRANSACTION = 108 + BABYLON_ORIGINATION = 109 + BABYLON_DELEGATION = 110 + ATHENS_REVEAL = 7 + ATHENS_TRANSACTION = 8 + ATHENS_ORIGINATION = 9 + ATHENS_DELEGATION = 10 + PREATTESTATION = 20 + ATTESTATION = 21 + ATTESTATION_WITH_DAL = 23 class Preattestation(Message): """Class representing a preattestation.""" @@ -168,6 +169,46 @@ def raw(self) -> bytes: raw += self.block_payload_hash return raw +class AttestationDal(Message): + """Class representing an attestation + DAL.""" + chain_id: int + branch: bytes + slot: int + op_level: int + op_round: int + block_payload_hash: bytes + dal_message: bytes + + def __init__(self, + chain_id: int, + branch: Union[str,bytes], + slot: int, + op_level: int, + op_round: int, + block_payload_hash: Union[str,bytes], + dal_message: Union[str,bytes]): + self.chain_id = chain_id + self.branch = scrub(branch) + assert_data_size("branch", self.branch, 32) + self.slot = slot + self.op_level = op_level + self.op_round = op_round + self.block_payload_hash = scrub(block_payload_hash) + assert_data_size("block_payload_hash", self.block_payload_hash, 32) + self.dal_message = scrub(dal_message) + + def raw(self) -> bytes: + raw = b'' + raw += MagicByte.TENDERBAKE_ENDORSEMENT.to_bytes(1, byteorder='big') + raw += self.chain_id.to_bytes(4, byteorder='big') + raw += self.branch + raw += OperationTag.ATTESTATION_WITH_DAL.to_bytes(1, byteorder='big') + raw += self.slot.to_bytes(2, byteorder='big') + raw += self.op_level.to_bytes(4, byteorder='big') + raw += self.op_round.to_bytes(4, byteorder='big') + raw += self.block_payload_hash + return raw + class Fitness: """Class representing a fitness.""" level: int