Skip to content

Commit c9c14b7

Browse files
authored
Merge pull request #3135 from IntersectMBO/gen_payment_key_with_mnemonic
feat(keys): add mnemonic-based payment key generation
2 parents e8a772d + 1fa3dd0 commit c9c14b7

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)