Skip to content

Commit

Permalink
Add cardano tests based on Shelley addresses
Browse files Browse the repository at this point in the history
  • Loading branch information
cedelavergne-ledger committed Nov 19, 2024
1 parent 0705da8 commit b7c7f1a
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 3 deletions.
45 changes: 45 additions & 0 deletions test/python/apps/cardano.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,48 @@ def perform_byron_sign_tx(self, path: str, destination: str, send_amount: int, s

self._check_signature_validity(path, signature, data)


def perform_shelley_sign_tx(self, path: str, destination: str, send_amount: int, send_fees: int) -> None:
"""Send a Sign TX command to the Cardano app.
Based on Shelley, address type DEVICE_OWNED
Args:
path (str): Derivation path
destination (str): Destination address
send_amount (int): Amount to send
send_fees (int): Fees to pay
Returns:
Tuple[bytes, bytes]: Data Hash and the Signature
"""

if destination is None:
raise ValueError(f"Invalid destination address: {destination}")

output_len = 4 + len(destination) // 2 + len(send_amount) // 2 + 6
signTx = {
# Based on ragger testsAlonzo: Sign tx with change output as array
"signTxInit": "d72101003c0000000000000000012d964a090201010101010101010107000000010000000100000000000000000000000000000000000000000000000000000001",
"signTxInputs": "d7210200243b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700000000",
"signTxOutputBasic": f"d7210330{output_len:02x}00020001{destination}{send_amount}000000000101",
"signTxOutputConfirm": "d721033300",
"signTxFees": f"d721040008{send_fees}",
"signTxTtl": "d721050008000000000000000a",
"signTxConfirm": "d7210a0000",
"signTxWitness": f"d7210f0015{pack_derivation_path(path).hex()}",
}

data: str = ""
signature: str = ""
for step, value in signTx.items():
response = self._backend.exchange_raw(bytes.fromhex(value))
assert response.status == Errors.SW_SUCCESS
if step == "signTxConfirm":
# Retrieve the data hash
data = response.data
elif step == "signTxWitness":
# Retrieve the signature
signature = response.data

self._check_signature_validity(path, signature, data)

60 changes: 57 additions & 3 deletions test/python/test_cardano.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import pytest
import base58

from ragger.bip import pack_derivation_path

from .apps.exchange_test_runner import ExchangeTestRunner, ALL_TESTS_EXCEPT_MEMO_AND_THORSWAP
from .apps.cardano import CardanoClient, Errors
from .apps.cardano import ADA_BYRON_DERIVATION_PATH
from .apps.cardano import ADA_BYRON_DERIVATION_PATH, ADA_SHELLEY_DERIVATION_PATH
from .apps import cal as cal


Expand All @@ -30,9 +32,61 @@ def perform_final_tx(self, destination: str, send_amount: int, fees: int, memo)
f"{fees:016x}")


def _craft_shelley_destination(path1: str, path2: str) -> str:
"""Craft a valid Shelley destination address
Args:
path1 (str): The first derivation path
path2 (str): The second derivation path
Returns:
str: The crafted destination address
"""
return f"{pack_derivation_path(path1).hex()}22{pack_derivation_path(path2).hex()}"


SHELLEY_DESTINATION = {
"valid_1": {
"addr": "addr_test1qqqstqqqqu7gqqq8z7qqqqqqqqqqqqqqqqqqzgs9sqqqw0yqqqr30qqqqqqqqqqqqgqqqqqpkk30k4",
"path": _craft_shelley_destination("m/1852'/1815'/0'/0/1", "m/1852'/1815'/0'/2/1")},
"valid_2": {
"addr": "addr_test1qqqstqqqqu7gqqq8z7qqqqqqqqqqqqqqqqqqygs9sqqqw0yqqqr30qqqqqqqqqqqqgqqqqqz2xv3eu",
"path": _craft_shelley_destination("m/1852'/1815'/0'/0/2", "m/1852'/1815'/0'/2/2")},
}

# ExchangeTestRunner implementation for Cardano
class CardanoShelleyClientTests(ExchangeTestRunner):

# Addresses Generated on MainNet, type BASE_PAYMENT_KEY_STAKE_KEY
currency_configuration = cal.ADA_SHELLEY_CURRENCY_CONFIGURATION
valid_destination_1 = SHELLEY_DESTINATION["valid_1"]["addr"]
valid_destination_2 = SHELLEY_DESTINATION["valid_2"]["addr"]
valid_refund = "addr1q9kl5z2zd9vakyprvw0g68c8hv0y0rnj93htc82hh2rs8wwmyx0wtn56wnuclkku9hsnal8dtg25a7x56svjn4dlnlmq7quz6p"
valid_send_amount_1 = 7120787
valid_send_amount_2 = 446739662
valid_fees_1 = 42
valid_fees_2 = 28
fake_refund = "abcdabcd"
fake_payout = "abcdabcd"
signature_refusal_error_code = Errors.SW_SWAP_CHECKING_FAIL

def perform_final_tx(self, destination: str, send_amount: int, fees: int, memo) -> None:
# Create a reverse lookup dictionary
addr_to_path = {v["addr"]: v["path"] for v in SHELLEY_DESTINATION.values()}
CardanoClient(self.backend).perform_shelley_sign_tx(ADA_SHELLEY_DERIVATION_PATH,
addr_to_path.get(destination),
f"{send_amount:016x}",
f"{fees:016x}")


# Use a class to reuse the same Speculos instance
class TestsCardanoClient:

# Test Ready, but legacy and unused address format
# @pytest.mark.parametrize('test_to_run', ALL_TESTS_EXCEPT_MEMO_AND_THORSWAP)
# def test_cardano_byron(self, backend, exchange_navigation_helper, test_to_run):
# CardanoByronClientTests(backend, exchange_navigation_helper).run_test(test_to_run)

@pytest.mark.parametrize('test_to_run', ALL_TESTS_EXCEPT_MEMO_AND_THORSWAP)
def test_cardano(self, backend, exchange_navigation_helper, test_to_run):
CardanoByronClientTests(backend, exchange_navigation_helper).run_test(test_to_run)
def test_cardano_shelley(self, backend, exchange_navigation_helper, test_to_run):
CardanoShelleyClientTests(backend, exchange_navigation_helper).run_test(test_to_run)

0 comments on commit b7c7f1a

Please sign in to comment.