Skip to content

Commit

Permalink
feat(cardano): conway stake reg certificate
Browse files Browse the repository at this point in the history
  • Loading branch information
jaskp committed Nov 7, 2023
1 parent 72c52f2 commit bfad4c7
Show file tree
Hide file tree
Showing 11 changed files with 224 additions and 73 deletions.
2 changes: 2 additions & 0 deletions common/protob/messages-cardano.proto
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ enum CardanoCertificateType {
STAKE_DEREGISTRATION = 1;
STAKE_DELEGATION = 2;
STAKE_POOL_REGISTRATION = 3;
STAKE_REGISTRATION_CONWAY = 7;
}

enum CardanoPoolRelayType {
Expand Down Expand Up @@ -346,6 +347,7 @@ message CardanoTxCertificate {
optional CardanoPoolParametersType pool_parameters = 4; // used for stake pool registration certificate
optional bytes script_hash = 5; // stake credential script hash
optional bytes key_hash = 6; // stake credential key hash
optional uint64 coins = 7; // used for stake key registration certificate
}

/**
Expand Down
53 changes: 53 additions & 0 deletions common/tests/fixtures/cardano/sign_tx.json
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,59 @@
]
}
},
{
"description": "transaction with conway stake registration certificate",
"parameters": {
"protocol_magic": 764824073,
"network_id": 1,
"fee": 42,
"ttl": 10,
"validity_interval_start": null,
"certificates": [
{
"type": 7,
"path": "m/1852'/1815'/0'/2/0",
"coins": 2000000
}
],
"withdrawals": [],
"auxiliary_data": null,
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
"prev_index": 0
}
],
"outputs": [
{
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
"amount": "1"
}
],
"mint": [],
"script_data_hash": null,
"collateral_inputs": [],
"required_signers": [],
"collateral_return": null,
"total_collateral": null,
"reference_inputs": [],
"signing_mode": "ORDINARY_TRANSACTION",
"additional_witness_requests": [],
"include_network_id": false
},
"result": {
"tx_hash": "e200b2c91f3493a1f3b9cfc8b6c141f70181741025e53941e9d57d22b1470c5c",
"witnesses": [
{
"type": 1,
"pub_key": "5d010cf16fdeff40955633d6c565f3844a288a24967cf6b76acbeb271b4f13c1",
"signature": "79a357517a08c7256b0fab1e93a92a477386f4c2d72cea7bc68527c0133c32472305f010350665d72e8017bb6c2080b5742680ce7700bbddda561c917f294a07",
"chain_code": null
}
]
}
},
{
"description": "transaction with stake registration certificate (no outputs)",
"parameters": {
Expand Down
21 changes: 18 additions & 3 deletions core/src/apps/cardano/certificates.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def validate(
if certificate.type in (
CCT.STAKE_DELEGATION,
CCT.STAKE_REGISTRATION,
CCT.STAKE_REGISTRATION_CONWAY,
CCT.STAKE_DEREGISTRATION,
):
validate_stake_credential(
Expand All @@ -68,17 +69,20 @@ def validate(
def _validate_structure(certificate: messages.CardanoTxCertificate) -> None:
pool = certificate.pool # local_cache_attribute
pool_parameters = certificate.pool_parameters # local_cache_attribute
coins = certificate.coins
CCT = CardanoCertificateType # local_cache_global

fields_to_be_empty: dict[CCT, tuple[Any, ...]] = {
CCT.STAKE_REGISTRATION: (pool, pool_parameters),
CCT.STAKE_DELEGATION: (pool_parameters,),
CCT.STAKE_DEREGISTRATION: (pool, pool_parameters),
CCT.STAKE_REGISTRATION: (pool, pool_parameters, coins),
CCT.STAKE_REGISTRATION_CONWAY: (pool, pool_parameters),
CCT.STAKE_DELEGATION: (pool_parameters, coins),
CCT.STAKE_DEREGISTRATION: (pool, pool_parameters, coins),
CCT.STAKE_POOL_REGISTRATION: (
certificate.path,
certificate.script_hash,
certificate.key_hash,
pool,
coins,
),
}

Expand Down Expand Up @@ -106,6 +110,17 @@ def cborize(
certificate.key_hash,
),
)
elif cert_type == CardanoCertificateType.STAKE_REGISTRATION_CONWAY:
return (
cert_type,
cborize_stake_credential(
keychain,
certificate.path,
certificate.script_hash,
certificate.key_hash,
),
certificate.coins,
)
elif cert_type == CardanoCertificateType.STAKE_DELEGATION:
return (
cert_type,
Expand Down
8 changes: 7 additions & 1 deletion core/src/apps/cardano/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@

CERTIFICATE_TYPE_NAMES = {
CardanoCertificateType.STAKE_REGISTRATION: "Stake key registration",
CardanoCertificateType.STAKE_REGISTRATION_CONWAY: "Stake key registration with deposit",
CardanoCertificateType.STAKE_DEREGISTRATION: "Stake key deregistration",
CardanoCertificateType.STAKE_DELEGATION: "Stake delegation",
CardanoCertificateType.STAKE_POOL_REGISTRATION: "Stakepool registration",
Expand Down Expand Up @@ -532,7 +533,9 @@ async def confirm_tx(
)


async def confirm_certificate(certificate: messages.CardanoTxCertificate) -> None:
async def confirm_certificate(
certificate: messages.CardanoTxCertificate, network_id: int
) -> None:
# stake pool registration requires custom confirmation logic not covered
# in this call
assert certificate.type != CardanoCertificateType.STAKE_POOL_REGISTRATION
Expand All @@ -547,6 +550,9 @@ async def confirm_certificate(certificate: messages.CardanoTxCertificate) -> Non
if certificate.type == CardanoCertificateType.STAKE_DELEGATION:
assert certificate.pool is not None # validate_certificate
props.append(("to pool:", format_stake_pool_id(certificate.pool)))
elif certificate.type == CardanoCertificateType.STAKE_REGISTRATION_CONWAY:
assert certificate.coins is not None
props.append(("deposit:", format_coin_amount(certificate.coins, network_id)))

await confirm_properties(
"confirm_certificate",
Expand Down
2 changes: 1 addition & 1 deletion core/src/apps/cardano/sign_tx/signer.py
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,7 @@ async def _show_certificate(
certificate.pool_parameters.metadata
)
else:
await layout.confirm_certificate(certificate)
await layout.confirm_certificate(certificate, self.msg.network_id)

# pool owners

Expand Down
1 change: 1 addition & 0 deletions core/src/trezor/enums/CardanoCertificateType.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
STAKE_DEREGISTRATION = 1
STAKE_DELEGATION = 2
STAKE_POOL_REGISTRATION = 3
STAKE_REGISTRATION_CONWAY = 7
1 change: 1 addition & 0 deletions core/src/trezor/enums/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@ class CardanoCertificateType(IntEnum):
STAKE_DEREGISTRATION = 1
STAKE_DELEGATION = 2
STAKE_POOL_REGISTRATION = 3
STAKE_REGISTRATION_CONWAY = 7

class CardanoPoolRelayType(IntEnum):
SINGLE_HOST_IP = 0
Expand Down
2 changes: 2 additions & 0 deletions core/src/trezor/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -1617,6 +1617,7 @@ class CardanoTxCertificate(protobuf.MessageType):
pool_parameters: "CardanoPoolParametersType | None"
script_hash: "bytes | None"
key_hash: "bytes | None"
coins: "int | None"

def __init__(
self,
Expand All @@ -1627,6 +1628,7 @@ def __init__(
pool_parameters: "CardanoPoolParametersType | None" = None,
script_hash: "bytes | None" = None,
key_hash: "bytes | None" = None,
coins: "int | None" = None,
) -> None:
pass

Expand Down
18 changes: 18 additions & 0 deletions python/src/trezorlib/cardano.py
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,24 @@ def parse_certificate(certificate: dict) -> CertificateWithPoolOwnersAndRelays:
),
None,
)
elif certificate_type == messages.CardanoCertificateType.STAKE_REGISTRATION_CONWAY:
if "coins" not in certificate:
raise CERTIFICATE_MISSING_FIELDS_ERROR

path, script_hash, key_hash = _parse_credential(
certificate, CERTIFICATE_MISSING_FIELDS_ERROR
)

return (
messages.CardanoTxCertificate(
type=certificate_type,
path=path,
script_hash=script_hash,
key_hash=key_hash,
coins=int(certificate["coins"]),
),
None,
)
elif certificate_type == messages.CardanoCertificateType.STAKE_POOL_REGISTRATION:
pool_parameters = certificate["pool_parameters"]

Expand Down
4 changes: 4 additions & 0 deletions python/src/trezorlib/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,7 @@ class CardanoCertificateType(IntEnum):
STAKE_DEREGISTRATION = 1
STAKE_DELEGATION = 2
STAKE_POOL_REGISTRATION = 3
STAKE_REGISTRATION_CONWAY = 7


class CardanoPoolRelayType(IntEnum):
Expand Down Expand Up @@ -2631,6 +2632,7 @@ class CardanoTxCertificate(protobuf.MessageType):
4: protobuf.Field("pool_parameters", "CardanoPoolParametersType", repeated=False, required=False, default=None),
5: protobuf.Field("script_hash", "bytes", repeated=False, required=False, default=None),
6: protobuf.Field("key_hash", "bytes", repeated=False, required=False, default=None),
7: protobuf.Field("coins", "uint64", repeated=False, required=False, default=None),
}

def __init__(
Expand All @@ -2642,13 +2644,15 @@ def __init__(
pool_parameters: Optional["CardanoPoolParametersType"] = None,
script_hash: Optional["bytes"] = None,
key_hash: Optional["bytes"] = None,
coins: Optional["int"] = None,
) -> None:
self.path: Sequence["int"] = path if path is not None else []
self.type = type
self.pool = pool
self.pool_parameters = pool_parameters
self.script_hash = script_hash
self.key_hash = key_hash
self.coins = coins


class CardanoTxWithdrawal(protobuf.MessageType):
Expand Down
Loading

0 comments on commit bfad4c7

Please sign in to comment.