Skip to content

Commit 1fa3dd0

Browse files
committed
feat(keys): add mnemonic-based payment key generation
Introduce support for generating payment addresses and keys using mnemonics. Update utility functions and tests to allow selection of key generation method (direct or mnemonic). This enhances flexibility for address creation and testing scenarios.
1 parent e8a772d commit 1fa3dd0

File tree

3 files changed

+91
-8
lines changed

3 files changed

+91
-8
lines changed

cardano_node_tests/tests/common.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,7 @@ def get_payment_addrs(
454454
caching_key: str = "",
455455
amount: int | None = None,
456456
min_amount: int | None = None,
457+
key_gen_method: clusterlib_utils.KeyGenMethods = clusterlib_utils.KeyGenMethods.DIRECT,
457458
) -> list[clusterlib.AddressRecord]:
458459
"""Create new payment addresses."""
459460
if num < 1:
@@ -464,6 +465,7 @@ def _create_addrs() -> list[clusterlib.AddressRecord]:
464465
addrs = clusterlib_utils.create_payment_addr_records(
465466
*[f"{name_template}_fund_addr_{i}" for i in range(1, num + 1)],
466467
cluster_obj=cluster_obj,
468+
key_gen_method=key_gen_method,
467469
)
468470
return addrs
469471

@@ -486,6 +488,7 @@ def get_payment_addr(
486488
caching_key: str = "",
487489
amount: int | None = None,
488490
min_amount: int | None = None,
491+
key_gen_method: clusterlib_utils.KeyGenMethods = clusterlib_utils.KeyGenMethods.DIRECT,
489492
) -> clusterlib.AddressRecord:
490493
"""Create a single new payment address."""
491494
return get_payment_addrs(
@@ -496,6 +499,7 @@ def get_payment_addr(
496499
caching_key=caching_key,
497500
amount=amount,
498501
min_amount=min_amount,
502+
key_gen_method=key_gen_method,
499503
)[0]
500504

501505

@@ -508,6 +512,7 @@ def get_pool_users(
508512
caching_key: str = "",
509513
amount: int | None = None,
510514
min_amount: int | None = None,
515+
payment_key_gen_method: clusterlib_utils.KeyGenMethods = clusterlib_utils.KeyGenMethods.DIRECT,
511516
) -> list[clusterlib.PoolUser]:
512517
"""Create new pool users."""
513518
if num < 1:
@@ -519,6 +524,7 @@ def _create_pool_users() -> list[clusterlib.PoolUser]:
519524
cluster_obj=cluster_obj,
520525
name_template=f"{name_template}_pool_user",
521526
no_of_addr=num,
527+
payment_key_gen_method=payment_key_gen_method,
522528
)
523529
return users
524530

@@ -541,6 +547,7 @@ def get_pool_user(
541547
caching_key: str = "",
542548
amount: int | None = None,
543549
min_amount: int | None = None,
550+
payment_key_gen_method: clusterlib_utils.KeyGenMethods = clusterlib_utils.KeyGenMethods.DIRECT,
544551
) -> clusterlib.PoolUser:
545552
"""Create a single new pool user."""
546553
return get_pool_users(
@@ -551,6 +558,7 @@ def get_pool_user(
551558
caching_key=caching_key,
552559
amount=amount,
553560
min_amount=min_amount,
561+
payment_key_gen_method=payment_key_gen_method,
554562
)[0]
555563

556564

cardano_node_tests/tests/test_tx_basic.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ def payment_addrs_disposable(
8989
cluster_manager=cluster_manager,
9090
cluster_obj=cluster,
9191
num=2,
92+
key_gen_method=clusterlib_utils.KeyGenMethods.MNEMONIC,
9293
)
9394
return addrs
9495

cardano_node_tests/utils/clusterlib_utils.py

Lines changed: 82 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33
import base64
44
import dataclasses
5+
import enum
56
import itertools
67
import json
78
import logging
89
import math
910
import pathlib as pl
11+
import random
1012
import time
1113
import typing as tp
1214

@@ -58,6 +60,11 @@ class BuildMethods:
5860
BUILD_EST: tp.Final[str] = "build_estimate"
5961

6062

63+
class KeyGenMethods(enum.StrEnum):
64+
DIRECT = "direct"
65+
MNEMONIC = "mnemonic"
66+
67+
6168
def build_and_submit_tx(
6269
cluster_obj: clusterlib.ClusterLib,
6370
name_template: str,
@@ -371,21 +378,86 @@ def deregister_stake_address(
371378
return tx_output
372379

373380

381+
def gen_payment_addr_and_keys_from_mnemonic(
382+
name: str,
383+
cluster_obj: clusterlib.ClusterLib,
384+
size: tp.Literal[12, 15, 18, 21, 24] = 24,
385+
stake_vkey_file: cl_types.FileType | None = None,
386+
stake_script_file: cl_types.FileType | None = None,
387+
destination_dir: cl_types.FileType = ".",
388+
) -> clusterlib.AddressRecord:
389+
"""Generate payment address and key pair.
390+
391+
Args:
392+
cluster_obj: An instance of `clusterlib.ClusterLib`.
393+
size: Number of words in the mnemonic (12, 15, 18, 21, or 24).
394+
name: A name of the address and key pair.
395+
stake_vkey_file: A path to corresponding stake vkey file (optional).
396+
stake_script_file: A path to corresponding payment script file (optional).
397+
destination_dir: A path to directory for storing artifacts (optional).
398+
399+
Returns:
400+
clusterlib.AddressRecord: A data container containing the address and
401+
key pair / script file.
402+
"""
403+
mnemonic_file = pl.Path(destination_dir) / f"{name}_mnemonic"
404+
cluster_obj.g_key.gen_mnemonic(size=size, out_file=mnemonic_file)
405+
skey_file = cluster_obj.g_key.derive_from_mnemonic(
406+
key_name=name,
407+
key_type=clusterlib.KeyType.PAYMENT,
408+
mnemonic_file=mnemonic_file,
409+
key_number=0,
410+
destination_dir=destination_dir,
411+
)
412+
vkey_file = cluster_obj.g_key.gen_verification_key(
413+
key_name=name, signing_key_file=skey_file, destination_dir=destination_dir
414+
)
415+
key_pair = clusterlib.KeyPair(vkey_file=vkey_file, skey_file=skey_file)
416+
addr = cluster_obj.g_address.gen_payment_addr(
417+
addr_name=name,
418+
payment_vkey_file=key_pair.vkey_file,
419+
stake_vkey_file=stake_vkey_file,
420+
stake_script_file=stake_script_file,
421+
destination_dir=destination_dir,
422+
)
423+
424+
return clusterlib.AddressRecord(
425+
address=addr, vkey_file=key_pair.vkey_file, skey_file=key_pair.skey_file
426+
)
427+
428+
374429
def create_payment_addr_records(
375430
*names: str,
376431
cluster_obj: clusterlib.ClusterLib,
377432
stake_vkey_file: cl_types.FileType | None = None,
433+
key_gen_method: KeyGenMethods = KeyGenMethods.DIRECT,
378434
destination_dir: cl_types.FileType = ".",
379435
) -> list[clusterlib.AddressRecord]:
380436
"""Create new payment address(es)."""
381-
addrs = [
382-
cluster_obj.g_address.gen_payment_addr_and_keys(
383-
name=name,
384-
stake_vkey_file=stake_vkey_file,
385-
destination_dir=destination_dir,
386-
)
387-
for name in names
388-
]
437+
if key_gen_method == KeyGenMethods.DIRECT:
438+
addrs = [
439+
cluster_obj.g_address.gen_payment_addr_and_keys(
440+
name=name,
441+
stake_vkey_file=stake_vkey_file,
442+
destination_dir=destination_dir,
443+
)
444+
for name in names
445+
]
446+
elif key_gen_method == KeyGenMethods.MNEMONIC:
447+
size = random.choice((12, 15, 18, 21, 24))
448+
addrs = [
449+
gen_payment_addr_and_keys_from_mnemonic(
450+
name=f"{name}_size{size}",
451+
cluster_obj=cluster_obj,
452+
size=size, # type: ignore
453+
stake_vkey_file=stake_vkey_file,
454+
destination_dir=destination_dir,
455+
)
456+
for name in names
457+
]
458+
else:
459+
err = f"Unsupported key generation method '{key_gen_method}'"
460+
raise ValueError(err)
389461

390462
LOGGER.debug(f"Created {len(addrs)} payment address(es)")
391463
return addrs
@@ -412,6 +484,7 @@ def create_pool_users(
412484
cluster_obj: clusterlib.ClusterLib,
413485
name_template: str,
414486
no_of_addr: int = 1,
487+
payment_key_gen_method: KeyGenMethods = KeyGenMethods.DIRECT,
415488
destination_dir: cl_types.FileType = ".",
416489
) -> list[clusterlib.PoolUser]:
417490
"""Create PoolUsers."""
@@ -425,6 +498,7 @@ def create_pool_users(
425498
f"{name_template}_addr_{i}",
426499
cluster_obj=cluster_obj,
427500
stake_vkey_file=stake_addr_rec.vkey_file,
501+
key_gen_method=payment_key_gen_method,
428502
destination_dir=destination_dir,
429503
)[0]
430504
# Create pool user struct

0 commit comments

Comments
 (0)