hippius 0.2.49__tar.gz → 0.2.50__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {hippius-0.2.49 → hippius-0.2.50}/PKG-INFO +1 -1
- {hippius-0.2.49 → hippius-0.2.50}/hippius_sdk/__init__.py +1 -1
- {hippius-0.2.49 → hippius-0.2.50}/hippius_sdk/cli.py +18 -18
- {hippius-0.2.49 → hippius-0.2.50}/hippius_sdk/cli_handlers.py +162 -124
- {hippius-0.2.49 → hippius-0.2.50}/hippius_sdk/cli_parser.py +59 -37
- {hippius-0.2.49 → hippius-0.2.50}/pyproject.toml +1 -1
- {hippius-0.2.49 → hippius-0.2.50}/README.md +0 -0
- {hippius-0.2.49 → hippius-0.2.50}/hippius_sdk/cli_assets.py +0 -0
- {hippius-0.2.49 → hippius-0.2.50}/hippius_sdk/cli_rich.py +0 -0
- {hippius-0.2.49 → hippius-0.2.50}/hippius_sdk/client.py +0 -0
- {hippius-0.2.49 → hippius-0.2.50}/hippius_sdk/config.py +0 -0
- {hippius-0.2.49 → hippius-0.2.50}/hippius_sdk/db/README.md +0 -0
- {hippius-0.2.49 → hippius-0.2.50}/hippius_sdk/db/env.db.template +0 -0
- {hippius-0.2.49 → hippius-0.2.50}/hippius_sdk/db/migrations/20241201000001_create_key_storage_tables.sql +0 -0
- {hippius-0.2.49 → hippius-0.2.50}/hippius_sdk/db/migrations/20241202000001_switch_to_subaccount_encryption.sql +0 -0
- {hippius-0.2.49 → hippius-0.2.50}/hippius_sdk/db/setup_database.sh +0 -0
- {hippius-0.2.49 → hippius-0.2.50}/hippius_sdk/db_utils.py +0 -0
- {hippius-0.2.49 → hippius-0.2.50}/hippius_sdk/errors.py +0 -0
- {hippius-0.2.49 → hippius-0.2.50}/hippius_sdk/incentives.py +0 -0
- {hippius-0.2.49 → hippius-0.2.50}/hippius_sdk/ipfs.py +0 -0
- {hippius-0.2.49 → hippius-0.2.50}/hippius_sdk/ipfs_core.py +0 -0
- {hippius-0.2.49 → hippius-0.2.50}/hippius_sdk/key_storage.py +0 -0
- {hippius-0.2.49 → hippius-0.2.50}/hippius_sdk/substrate.py +0 -0
- {hippius-0.2.49 → hippius-0.2.50}/hippius_sdk/utils.py +0 -0
@@ -26,7 +26,7 @@ from hippius_sdk.config import (
|
|
26
26
|
from hippius_sdk.ipfs import IPFSClient, S3PublishResult, S3DownloadResult
|
27
27
|
from hippius_sdk.utils import format_cid, format_size, hex_to_ipfs_cid
|
28
28
|
|
29
|
-
__version__ = "0.2.
|
29
|
+
__version__ = "0.2.50"
|
30
30
|
__all__ = [
|
31
31
|
"HippiusClient",
|
32
32
|
"IPFSClient",
|
@@ -418,15 +418,15 @@ def main():
|
|
418
418
|
args.node_id,
|
419
419
|
args.node_priv_hex,
|
420
420
|
args.node_type,
|
421
|
-
ipfs_config=getattr(args,
|
422
|
-
ipfs_priv_b64=getattr(args,
|
423
|
-
ipfs_peer_id=getattr(args,
|
424
|
-
pay_in_credits=getattr(args,
|
425
|
-
expires_in=getattr(args,
|
426
|
-
block_width=getattr(args,
|
427
|
-
domain=getattr(args,
|
428
|
-
nonce_hex=getattr(args,
|
429
|
-
dry_run=getattr(args,
|
421
|
+
ipfs_config=getattr(args, "ipfs_config", None),
|
422
|
+
ipfs_priv_b64=getattr(args, "ipfs_priv_b64", None),
|
423
|
+
ipfs_peer_id=getattr(args, "ipfs_peer_id", None),
|
424
|
+
pay_in_credits=getattr(args, "pay_in_credits", False),
|
425
|
+
expires_in=getattr(args, "expires_in", 10),
|
426
|
+
block_width=getattr(args, "block_width", "u32"),
|
427
|
+
domain=getattr(args, "domain", "HIPPIUS::REGISTER::v1"),
|
428
|
+
nonce_hex=getattr(args, "nonce_hex", None),
|
429
|
+
dry_run=getattr(args, "dry_run", False),
|
430
430
|
)
|
431
431
|
elif args.miner_action == "register-hotkey":
|
432
432
|
return run_async_handler(
|
@@ -436,15 +436,15 @@ def main():
|
|
436
436
|
args.node_id,
|
437
437
|
args.node_priv_hex,
|
438
438
|
args.node_type,
|
439
|
-
ipfs_config=getattr(args,
|
440
|
-
ipfs_priv_b64=getattr(args,
|
441
|
-
ipfs_peer_id=getattr(args,
|
442
|
-
pay_in_credits=getattr(args,
|
443
|
-
expires_in=getattr(args,
|
444
|
-
block_width=getattr(args,
|
445
|
-
domain=getattr(args,
|
446
|
-
nonce_hex=getattr(args,
|
447
|
-
dry_run=getattr(args,
|
439
|
+
ipfs_config=getattr(args, "ipfs_config", None),
|
440
|
+
ipfs_priv_b64=getattr(args, "ipfs_priv_b64", None),
|
441
|
+
ipfs_peer_id=getattr(args, "ipfs_peer_id", None),
|
442
|
+
pay_in_credits=getattr(args, "pay_in_credits", False),
|
443
|
+
expires_in=getattr(args, "expires_in", 10),
|
444
|
+
block_width=getattr(args, "block_width", "u32"),
|
445
|
+
domain=getattr(args, "domain", "HIPPIUS::REGISTER::v1"),
|
446
|
+
nonce_hex=getattr(args, "nonce_hex", None),
|
447
|
+
dry_run=getattr(args, "dry_run", False),
|
448
448
|
)
|
449
449
|
else:
|
450
450
|
# Display the Hippius logo banner with Rich formatting
|
@@ -3313,54 +3313,63 @@ def handle_register_coldkey(
|
|
3313
3313
|
# Get current account info
|
3314
3314
|
account = get_active_account()
|
3315
3315
|
if not account:
|
3316
|
-
error(
|
3316
|
+
error(
|
3317
|
+
"No active account. Please set up an account first with 'hippius account create' or 'hippius seed set'"
|
3318
|
+
)
|
3317
3319
|
return 1
|
3318
|
-
|
3320
|
+
|
3319
3321
|
account_address = get_account_address(account)
|
3320
3322
|
if not account_address:
|
3321
3323
|
error(f"Could not get address for account '{account}'")
|
3322
3324
|
return 1
|
3323
|
-
|
3324
|
-
info(
|
3325
|
-
|
3325
|
+
|
3326
|
+
info(
|
3327
|
+
f"Registering node with coldkey using account: [bold cyan]{account}[/bold cyan] ({account_address})"
|
3328
|
+
)
|
3329
|
+
|
3326
3330
|
# Import and use incentives.py functionality
|
3327
3331
|
from hippius_sdk.incentives import (
|
3328
|
-
load_ipfs_seed,
|
3329
|
-
|
3330
|
-
|
3332
|
+
load_ipfs_seed,
|
3333
|
+
load_main_seed,
|
3334
|
+
encode_account_id,
|
3335
|
+
verify_peer_id,
|
3336
|
+
blake2_256,
|
3337
|
+
manual_encode_challenge,
|
3338
|
+
get_peer_id_from_public_key,
|
3339
|
+
get_public_key_from_peer_id,
|
3331
3340
|
)
|
3332
3341
|
from substrateinterface import SubstrateInterface, Keypair
|
3333
3342
|
from nacl.signing import SigningKey
|
3334
3343
|
import base58
|
3335
3344
|
import secrets
|
3336
3345
|
from binascii import hexlify
|
3337
|
-
|
3346
|
+
|
3338
3347
|
# Initialize SubstrateInterface
|
3339
3348
|
substrate = SubstrateInterface(url=client.substrate_client.url)
|
3340
|
-
|
3349
|
+
|
3341
3350
|
# Get genesis hash and current block
|
3342
3351
|
genesis_hash_hex = substrate.get_block_hash(0)
|
3343
3352
|
genesis_hash = bytes.fromhex(genesis_hash_hex[2:])
|
3344
3353
|
current_block_number = substrate.get_block_number(None)
|
3345
|
-
|
3354
|
+
|
3346
3355
|
log(f"Current block number: {current_block_number}")
|
3347
|
-
|
3356
|
+
|
3348
3357
|
# Process node_id
|
3349
3358
|
if node_id.startswith("0x"):
|
3350
3359
|
node_id_bytes = bytes.fromhex(node_id[2:])
|
3351
3360
|
else:
|
3352
3361
|
node_id_bytes = base58.b58decode(node_id)
|
3353
|
-
|
3362
|
+
|
3354
3363
|
# Load IPFS and main seeds
|
3355
3364
|
ipfs_seed, peerid_from_config = load_ipfs_seed(ipfs_config, ipfs_priv_b64)
|
3356
3365
|
main_seed = load_main_seed(node_priv_hex)
|
3357
|
-
|
3366
|
+
|
3358
3367
|
# Create signing keys
|
3359
3368
|
main_sk = SigningKey(main_seed)
|
3360
3369
|
main_pk = bytes(main_sk.verify_key)
|
3361
3370
|
ipfs_sk = SigningKey(ipfs_seed)
|
3362
3371
|
ipfs_pk = bytes(ipfs_sk.verify_key)
|
3363
|
-
|
3372
|
+
|
3364
3373
|
# Handle IPFS peer ID
|
3365
3374
|
if ipfs_peer_id:
|
3366
3375
|
ipfs_peer_id_bytes = base58.b58decode(ipfs_peer_id)
|
@@ -3368,121 +3377,131 @@ def handle_register_coldkey(
|
|
3368
3377
|
ipfs_peer_id_bytes = base58.b58decode(peerid_from_config)
|
3369
3378
|
else:
|
3370
3379
|
if node_type in ["StorageMiner", "Validator"]:
|
3371
|
-
error(
|
3380
|
+
error(
|
3381
|
+
"IPFS PeerID is required for StorageMiner and Validator node types"
|
3382
|
+
)
|
3372
3383
|
return 1
|
3373
|
-
ipfs_peer_id_bytes = b
|
3374
|
-
|
3384
|
+
ipfs_peer_id_bytes = b""
|
3385
|
+
|
3375
3386
|
# Verify keys match node IDs
|
3376
3387
|
if not verify_peer_id(main_pk, node_id_bytes, "Ed25519"):
|
3377
3388
|
error("Main public key does not match node ID")
|
3378
3389
|
return 1
|
3379
|
-
|
3380
|
-
if ipfs_peer_id_bytes and not verify_peer_id(
|
3390
|
+
|
3391
|
+
if ipfs_peer_id_bytes and not verify_peer_id(
|
3392
|
+
ipfs_pk, ipfs_peer_id_bytes, "Ed25519"
|
3393
|
+
):
|
3381
3394
|
error("IPFS public key does not match peer ID")
|
3382
3395
|
return 1
|
3383
|
-
|
3396
|
+
|
3384
3397
|
# Create challenge data
|
3385
3398
|
domain_bytes = domain.encode()
|
3386
|
-
domain24 = b"HIPPIUS::REGISTER::v1" + b"\x00"*3
|
3399
|
+
domain24 = b"HIPPIUS::REGISTER::v1" + b"\x00" * 3
|
3387
3400
|
node_id_hash = blake2_256(node_id_bytes)
|
3388
3401
|
ipfs_peer_id_hash = blake2_256(ipfs_peer_id_bytes)
|
3389
|
-
|
3390
|
-
nonce = (
|
3391
|
-
|
3392
|
-
|
3393
|
-
|
3402
|
+
|
3403
|
+
nonce = (
|
3404
|
+
bytes.fromhex(nonce_hex[2:])
|
3405
|
+
if nonce_hex and nonce_hex.startswith("0x")
|
3406
|
+
else bytes.fromhex(nonce_hex)
|
3407
|
+
if nonce_hex
|
3408
|
+
else secrets.token_bytes(32)
|
3409
|
+
)
|
3410
|
+
|
3394
3411
|
expires_at_block = current_block_number + expires_in
|
3395
3412
|
account_bytes = encode_account_id(account_address)
|
3396
|
-
|
3413
|
+
|
3397
3414
|
challenge_data = {
|
3398
|
-
|
3399
|
-
|
3400
|
-
|
3401
|
-
|
3402
|
-
|
3403
|
-
|
3404
|
-
|
3405
|
-
|
3415
|
+
"domain": domain24,
|
3416
|
+
"genesis_hash": genesis_hash,
|
3417
|
+
"account": account_bytes,
|
3418
|
+
"node_id_hash": node_id_hash,
|
3419
|
+
"ipfs_peer_id_hash": ipfs_peer_id_hash,
|
3420
|
+
"block_number": current_block_number,
|
3421
|
+
"nonce": nonce,
|
3422
|
+
"expires_at": expires_at_block,
|
3406
3423
|
}
|
3407
|
-
|
3424
|
+
|
3408
3425
|
challenge_bytes = manual_encode_challenge(challenge_data, block_width)
|
3409
|
-
|
3426
|
+
|
3410
3427
|
# Sign challenge
|
3411
3428
|
main_sig = main_sk.sign(challenge_bytes).signature
|
3412
3429
|
ipfs_sig = ipfs_sk.sign(challenge_bytes).signature
|
3413
|
-
|
3430
|
+
|
3414
3431
|
# Build call parameters
|
3415
3432
|
call_params = {
|
3416
3433
|
"node_type": node_type,
|
3417
3434
|
"node_id": node_id,
|
3418
|
-
"node_id_hex": "0x"+hexlify(node_id_bytes).decode(),
|
3435
|
+
"node_id_hex": "0x" + hexlify(node_id_bytes).decode(),
|
3419
3436
|
"pay_in_credits": pay_in_credits,
|
3420
3437
|
"ipfs_node_id": ipfs_peer_id,
|
3421
3438
|
"owner": account_address,
|
3422
3439
|
"ipfs_peer_id": ipfs_peer_id,
|
3423
|
-
"ipfs_id_hex": "0x"+hexlify(ipfs_peer_id_bytes).decode(),
|
3440
|
+
"ipfs_id_hex": "0x" + hexlify(ipfs_peer_id_bytes).decode(),
|
3424
3441
|
"main_key_type": "Ed25519",
|
3425
|
-
"main_public_key": "0x"+main_pk.hex(),
|
3426
|
-
"main_sig": "0x"+main_sig.hex(),
|
3442
|
+
"main_public_key": "0x" + main_pk.hex(),
|
3443
|
+
"main_sig": "0x" + main_sig.hex(),
|
3427
3444
|
"ipfs_key_type": "Ed25519",
|
3428
|
-
"ipfs_public_key": "0x"+ipfs_pk.hex(),
|
3429
|
-
"ipfs_sig": "0x"+ipfs_sig.hex(),
|
3430
|
-
"challenge_bytes": "0x"+challenge_bytes.hex(),
|
3445
|
+
"ipfs_public_key": "0x" + ipfs_pk.hex(),
|
3446
|
+
"ipfs_sig": "0x" + ipfs_sig.hex(),
|
3447
|
+
"challenge_bytes": "0x" + challenge_bytes.hex(),
|
3431
3448
|
}
|
3432
|
-
|
3449
|
+
|
3433
3450
|
if dry_run:
|
3434
3451
|
log("Dry run mode - printing payload without submitting")
|
3435
3452
|
payload = {
|
3436
|
-
"genesis_hash_hex": "0x"+genesis_hash.hex(),
|
3453
|
+
"genesis_hash_hex": "0x" + genesis_hash.hex(),
|
3437
3454
|
"current_block_number": current_block_number,
|
3438
|
-
"challenge_bytes_hex": "0x"+challenge_bytes.hex(),
|
3455
|
+
"challenge_bytes_hex": "0x" + challenge_bytes.hex(),
|
3439
3456
|
"call_module": "Registration",
|
3440
3457
|
"call_function": "register_node_with_coldkey",
|
3441
|
-
"call_params": call_params
|
3458
|
+
"call_params": call_params,
|
3442
3459
|
}
|
3443
3460
|
console.print(json.dumps(payload, indent=2))
|
3444
3461
|
return 0
|
3445
|
-
|
3462
|
+
|
3446
3463
|
# Get keypair for signing
|
3447
|
-
|
3464
|
+
from hippius_sdk.config import get_seed_phrase
|
3465
|
+
seed_phrase = get_seed_phrase()
|
3448
3466
|
if not seed_phrase:
|
3449
3467
|
error("No seed phrase available for signing transaction")
|
3450
3468
|
return 1
|
3451
|
-
|
3469
|
+
|
3452
3470
|
kp = Keypair.create_from_uri(seed_phrase)
|
3453
|
-
|
3471
|
+
|
3454
3472
|
# Submit transaction
|
3455
3473
|
log("Submitting registration transaction...")
|
3456
3474
|
call = substrate.compose_call(
|
3457
3475
|
call_module="Registration",
|
3458
3476
|
call_function="register_node_with_coldkey",
|
3459
|
-
call_params=call_params
|
3477
|
+
call_params=call_params,
|
3460
3478
|
)
|
3461
3479
|
extrinsic = substrate.create_signed_extrinsic(call=call, keypair=kp)
|
3462
3480
|
receipt = substrate.submit_extrinsic(extrinsic, wait_for_inclusion=True)
|
3463
|
-
|
3481
|
+
|
3464
3482
|
result = {
|
3465
3483
|
"extrinsic_hash": receipt.extrinsic_hash,
|
3466
3484
|
"is_success": receipt.is_success,
|
3467
3485
|
"error_message": receipt.error_message,
|
3468
|
-
"triggered_events": [str(event) for event in receipt.triggered_events]
|
3486
|
+
"triggered_events": [str(event) for event in receipt.triggered_events],
|
3469
3487
|
}
|
3470
|
-
|
3488
|
+
|
3471
3489
|
if receipt.is_success:
|
3472
3490
|
success(f"Node registered successfully with coldkey!")
|
3473
3491
|
success(f"Transaction hash: {receipt.extrinsic_hash}")
|
3474
3492
|
else:
|
3475
3493
|
error(f"Registration failed: {receipt.error_message}")
|
3476
|
-
|
3494
|
+
|
3477
3495
|
log("Full result:")
|
3478
3496
|
console.print(json.dumps(result, indent=2))
|
3479
|
-
|
3497
|
+
|
3480
3498
|
return 0 if receipt.is_success else 1
|
3481
|
-
|
3499
|
+
|
3482
3500
|
except Exception as e:
|
3483
3501
|
error(f"Error registering node with coldkey: {e}")
|
3484
|
-
if hasattr(e,
|
3502
|
+
if hasattr(e, "__traceback__"):
|
3485
3503
|
import traceback
|
3504
|
+
|
3486
3505
|
traceback.print_exc()
|
3487
3506
|
return 1
|
3488
3507
|
|
@@ -3508,55 +3527,64 @@ def handle_register_hotkey(
|
|
3508
3527
|
# Get current account info
|
3509
3528
|
account = get_active_account()
|
3510
3529
|
if not account:
|
3511
|
-
error(
|
3530
|
+
error(
|
3531
|
+
"No active account. Please set up an account first with 'hippius account create' or 'hippius seed set'"
|
3532
|
+
)
|
3512
3533
|
return 1
|
3513
|
-
|
3534
|
+
|
3514
3535
|
account_address = get_account_address(account)
|
3515
3536
|
if not account_address:
|
3516
3537
|
error(f"Could not get address for account '{account}'")
|
3517
3538
|
return 1
|
3518
|
-
|
3519
|
-
info(
|
3539
|
+
|
3540
|
+
info(
|
3541
|
+
f"Registering node with hotkey using account: [bold cyan]{account}[/bold cyan] ({account_address})"
|
3542
|
+
)
|
3520
3543
|
info(f"Coldkey: [bold yellow]{coldkey}[/bold yellow]")
|
3521
|
-
|
3544
|
+
|
3522
3545
|
# Import and use incentives.py functionality
|
3523
3546
|
from hippius_sdk.incentives import (
|
3524
|
-
load_ipfs_seed,
|
3525
|
-
|
3526
|
-
|
3547
|
+
load_ipfs_seed,
|
3548
|
+
load_main_seed,
|
3549
|
+
encode_account_id,
|
3550
|
+
verify_peer_id,
|
3551
|
+
blake2_256,
|
3552
|
+
manual_encode_challenge,
|
3553
|
+
get_peer_id_from_public_key,
|
3554
|
+
get_public_key_from_peer_id,
|
3527
3555
|
)
|
3528
3556
|
from substrateinterface import SubstrateInterface, Keypair
|
3529
3557
|
from nacl.signing import SigningKey
|
3530
3558
|
import base58
|
3531
3559
|
import secrets
|
3532
3560
|
from binascii import hexlify
|
3533
|
-
|
3561
|
+
|
3534
3562
|
# Initialize SubstrateInterface
|
3535
3563
|
substrate = SubstrateInterface(url=client.substrate_client.url)
|
3536
|
-
|
3564
|
+
|
3537
3565
|
# Get genesis hash and current block
|
3538
3566
|
genesis_hash_hex = substrate.get_block_hash(0)
|
3539
3567
|
genesis_hash = bytes.fromhex(genesis_hash_hex[2:])
|
3540
3568
|
current_block_number = substrate.get_block_number(None)
|
3541
|
-
|
3569
|
+
|
3542
3570
|
log(f"Current block number: {current_block_number}")
|
3543
|
-
|
3571
|
+
|
3544
3572
|
# Process node_id
|
3545
3573
|
if node_id.startswith("0x"):
|
3546
3574
|
node_id_bytes = bytes.fromhex(node_id[2:])
|
3547
3575
|
else:
|
3548
3576
|
node_id_bytes = base58.b58decode(node_id)
|
3549
|
-
|
3577
|
+
|
3550
3578
|
# Load IPFS and main seeds
|
3551
3579
|
ipfs_seed, peerid_from_config = load_ipfs_seed(ipfs_config, ipfs_priv_b64)
|
3552
3580
|
main_seed = load_main_seed(node_priv_hex)
|
3553
|
-
|
3581
|
+
|
3554
3582
|
# Create signing keys
|
3555
3583
|
main_sk = SigningKey(main_seed)
|
3556
3584
|
main_pk = bytes(main_sk.verify_key)
|
3557
3585
|
ipfs_sk = SigningKey(ipfs_seed)
|
3558
3586
|
ipfs_pk = bytes(ipfs_sk.verify_key)
|
3559
|
-
|
3587
|
+
|
3560
3588
|
# Handle IPFS peer ID
|
3561
3589
|
if ipfs_peer_id:
|
3562
3590
|
ipfs_peer_id_bytes = base58.b58decode(ipfs_peer_id)
|
@@ -3564,121 +3592,131 @@ def handle_register_hotkey(
|
|
3564
3592
|
ipfs_peer_id_bytes = base58.b58decode(peerid_from_config)
|
3565
3593
|
else:
|
3566
3594
|
if node_type in ["StorageMiner", "Validator"]:
|
3567
|
-
error(
|
3595
|
+
error(
|
3596
|
+
"IPFS PeerID is required for StorageMiner and Validator node types"
|
3597
|
+
)
|
3568
3598
|
return 1
|
3569
|
-
ipfs_peer_id_bytes = b
|
3570
|
-
|
3599
|
+
ipfs_peer_id_bytes = b""
|
3600
|
+
|
3571
3601
|
# Verify keys match node IDs
|
3572
3602
|
if not verify_peer_id(main_pk, node_id_bytes, "Ed25519"):
|
3573
3603
|
error("Main public key does not match node ID")
|
3574
3604
|
return 1
|
3575
|
-
|
3576
|
-
if ipfs_peer_id_bytes and not verify_peer_id(
|
3605
|
+
|
3606
|
+
if ipfs_peer_id_bytes and not verify_peer_id(
|
3607
|
+
ipfs_pk, ipfs_peer_id_bytes, "Ed25519"
|
3608
|
+
):
|
3577
3609
|
error("IPFS public key does not match peer ID")
|
3578
3610
|
return 1
|
3579
|
-
|
3611
|
+
|
3580
3612
|
# Create challenge data
|
3581
3613
|
domain_bytes = domain.encode()
|
3582
|
-
domain24 = b"HIPPIUS::REGISTER::v1" + b"\x00"*3
|
3614
|
+
domain24 = b"HIPPIUS::REGISTER::v1" + b"\x00" * 3
|
3583
3615
|
node_id_hash = blake2_256(node_id_bytes)
|
3584
3616
|
ipfs_peer_id_hash = blake2_256(ipfs_peer_id_bytes)
|
3585
|
-
|
3586
|
-
nonce = (
|
3587
|
-
|
3588
|
-
|
3589
|
-
|
3617
|
+
|
3618
|
+
nonce = (
|
3619
|
+
bytes.fromhex(nonce_hex[2:])
|
3620
|
+
if nonce_hex and nonce_hex.startswith("0x")
|
3621
|
+
else bytes.fromhex(nonce_hex)
|
3622
|
+
if nonce_hex
|
3623
|
+
else secrets.token_bytes(32)
|
3624
|
+
)
|
3625
|
+
|
3590
3626
|
expires_at_block = current_block_number + expires_in
|
3591
3627
|
account_bytes = encode_account_id(account_address)
|
3592
|
-
|
3628
|
+
|
3593
3629
|
challenge_data = {
|
3594
|
-
|
3595
|
-
|
3596
|
-
|
3597
|
-
|
3598
|
-
|
3599
|
-
|
3600
|
-
|
3601
|
-
|
3630
|
+
"domain": domain24,
|
3631
|
+
"genesis_hash": genesis_hash,
|
3632
|
+
"account": account_bytes,
|
3633
|
+
"node_id_hash": node_id_hash,
|
3634
|
+
"ipfs_peer_id_hash": ipfs_peer_id_hash,
|
3635
|
+
"block_number": current_block_number,
|
3636
|
+
"nonce": nonce,
|
3637
|
+
"expires_at": expires_at_block,
|
3602
3638
|
}
|
3603
|
-
|
3639
|
+
|
3604
3640
|
challenge_bytes = manual_encode_challenge(challenge_data, block_width)
|
3605
|
-
|
3641
|
+
|
3606
3642
|
# Sign challenge
|
3607
3643
|
main_sig = main_sk.sign(challenge_bytes).signature
|
3608
3644
|
ipfs_sig = ipfs_sk.sign(challenge_bytes).signature
|
3609
|
-
|
3645
|
+
|
3610
3646
|
# Build call parameters
|
3611
3647
|
call_params = {
|
3612
3648
|
"coldkey": coldkey,
|
3613
3649
|
"node_type": node_type,
|
3614
3650
|
"node_id": node_id,
|
3615
|
-
"node_id_hex": "0x"+hexlify(node_id_bytes).decode(),
|
3651
|
+
"node_id_hex": "0x" + hexlify(node_id_bytes).decode(),
|
3616
3652
|
"pay_in_credits": pay_in_credits,
|
3617
3653
|
"ipfs_node_id": ipfs_peer_id,
|
3618
3654
|
"ipfs_peer_id": ipfs_peer_id,
|
3619
|
-
"ipfs_id_hex": "0x"+hexlify(ipfs_peer_id_bytes).decode(),
|
3655
|
+
"ipfs_id_hex": "0x" + hexlify(ipfs_peer_id_bytes).decode(),
|
3620
3656
|
"owner": account_address,
|
3621
3657
|
"main_key_type": "Ed25519",
|
3622
|
-
"main_public_key": "0x"+main_pk.hex(),
|
3623
|
-
"main_sig": "0x"+main_sig.hex(),
|
3658
|
+
"main_public_key": "0x" + main_pk.hex(),
|
3659
|
+
"main_sig": "0x" + main_sig.hex(),
|
3624
3660
|
"ipfs_key_type": "Ed25519",
|
3625
|
-
"ipfs_public_key": "0x"+ipfs_pk.hex(),
|
3626
|
-
"ipfs_sig": "0x"+ipfs_sig.hex(),
|
3627
|
-
"challenge_bytes": "0x"+challenge_bytes.hex(),
|
3661
|
+
"ipfs_public_key": "0x" + ipfs_pk.hex(),
|
3662
|
+
"ipfs_sig": "0x" + ipfs_sig.hex(),
|
3663
|
+
"challenge_bytes": "0x" + challenge_bytes.hex(),
|
3628
3664
|
}
|
3629
|
-
|
3665
|
+
|
3630
3666
|
if dry_run:
|
3631
3667
|
log("Dry run mode - printing payload without submitting")
|
3632
3668
|
payload = {
|
3633
|
-
"genesis_hash_hex": "0x"+genesis_hash.hex(),
|
3669
|
+
"genesis_hash_hex": "0x" + genesis_hash.hex(),
|
3634
3670
|
"current_block_number": current_block_number,
|
3635
|
-
"challenge_bytes_hex": "0x"+challenge_bytes.hex(),
|
3671
|
+
"challenge_bytes_hex": "0x" + challenge_bytes.hex(),
|
3636
3672
|
"call_module": "Registration",
|
3637
3673
|
"call_function": "register_node_with_hotkey",
|
3638
|
-
"call_params": call_params
|
3674
|
+
"call_params": call_params,
|
3639
3675
|
}
|
3640
3676
|
console.print(json.dumps(payload, indent=2))
|
3641
3677
|
return 0
|
3642
|
-
|
3678
|
+
|
3643
3679
|
# Get keypair for signing
|
3644
|
-
|
3680
|
+
from hippius_sdk.config import get_seed_phrase
|
3681
|
+
seed_phrase = get_seed_phrase()
|
3645
3682
|
if not seed_phrase:
|
3646
3683
|
error("No seed phrase available for signing transaction")
|
3647
3684
|
return 1
|
3648
|
-
|
3685
|
+
|
3649
3686
|
kp = Keypair.create_from_uri(seed_phrase)
|
3650
|
-
|
3687
|
+
|
3651
3688
|
# Submit transaction
|
3652
3689
|
log("Submitting registration transaction...")
|
3653
3690
|
call = substrate.compose_call(
|
3654
3691
|
call_module="Registration",
|
3655
3692
|
call_function="register_node_with_hotkey",
|
3656
|
-
call_params=call_params
|
3693
|
+
call_params=call_params,
|
3657
3694
|
)
|
3658
3695
|
extrinsic = substrate.create_signed_extrinsic(call=call, keypair=kp)
|
3659
3696
|
receipt = substrate.submit_extrinsic(extrinsic, wait_for_inclusion=True)
|
3660
|
-
|
3697
|
+
|
3661
3698
|
result = {
|
3662
3699
|
"extrinsic_hash": receipt.extrinsic_hash,
|
3663
3700
|
"is_success": receipt.is_success,
|
3664
3701
|
"error_message": receipt.error_message,
|
3665
|
-
"triggered_events": [str(event) for event in receipt.triggered_events]
|
3702
|
+
"triggered_events": [str(event) for event in receipt.triggered_events],
|
3666
3703
|
}
|
3667
|
-
|
3704
|
+
|
3668
3705
|
if receipt.is_success:
|
3669
3706
|
success(f"Node registered successfully with hotkey!")
|
3670
3707
|
success(f"Transaction hash: {receipt.extrinsic_hash}")
|
3671
3708
|
else:
|
3672
3709
|
error(f"Registration failed: {receipt.error_message}")
|
3673
|
-
|
3710
|
+
|
3674
3711
|
log("Full result:")
|
3675
3712
|
console.print(json.dumps(result, indent=2))
|
3676
|
-
|
3713
|
+
|
3677
3714
|
return 0 if receipt.is_success else 1
|
3678
|
-
|
3715
|
+
|
3679
3716
|
except Exception as e:
|
3680
3717
|
error(f"Error registering node with hotkey: {e}")
|
3681
|
-
if hasattr(e,
|
3718
|
+
if hasattr(e, "__traceback__"):
|
3682
3719
|
import traceback
|
3720
|
+
|
3683
3721
|
traceback.print_exc()
|
3684
3722
|
return 1
|
@@ -667,64 +667,75 @@ def add_miner_commands(subparsers):
|
|
667
667
|
|
668
668
|
# Register coldkey command
|
669
669
|
register_coldkey_parser = miner_subparsers.add_parser(
|
670
|
-
"register-coldkey",
|
670
|
+
"register-coldkey",
|
671
|
+
help="Register a node with coldkey (current account becomes coldkey)",
|
671
672
|
)
|
672
|
-
|
673
|
+
|
673
674
|
# Required arguments for register-coldkey
|
674
675
|
register_coldkey_parser.add_argument(
|
675
676
|
"--node-id", required=True, help="Your main node_id (libp2p peer ID)"
|
676
677
|
)
|
677
678
|
register_coldkey_parser.add_argument(
|
678
|
-
"--node-priv-hex",
|
679
|
+
"--node-priv-hex",
|
680
|
+
required=True,
|
681
|
+
help="Main libp2p ed25519 private key hex (32/64B)",
|
679
682
|
)
|
680
683
|
register_coldkey_parser.add_argument(
|
681
|
-
"--node-type",
|
684
|
+
"--node-type",
|
685
|
+
required=True,
|
682
686
|
choices=["StorageMiner", "Validator", "ComputeMiner", "StorageS3", "GpuMiner"],
|
683
|
-
help="Type of miner node"
|
687
|
+
help="Type of miner node",
|
684
688
|
)
|
685
|
-
|
689
|
+
|
686
690
|
# IPFS configuration (one required)
|
687
691
|
ipfs_group = register_coldkey_parser.add_mutually_exclusive_group(required=True)
|
688
692
|
ipfs_group.add_argument(
|
689
693
|
"--ipfs-config", help="Path to IPFS config file (e.g. ~/.ipfs/config)"
|
690
694
|
)
|
691
695
|
ipfs_group.add_argument(
|
692
|
-
"--ipfs-priv-b64",
|
696
|
+
"--ipfs-priv-b64",
|
697
|
+
help="IPFS Identity.PrivKey base64 if not using --ipfs-config",
|
693
698
|
)
|
694
|
-
|
699
|
+
|
695
700
|
# Optional arguments
|
696
701
|
register_coldkey_parser.add_argument(
|
697
702
|
"--ipfs-peer-id", help="Optional override IPFS PeerID"
|
698
703
|
)
|
699
704
|
register_coldkey_parser.add_argument(
|
700
|
-
"--pay-in-credits", action="store_true",
|
701
|
-
help="Pay in credits for registration"
|
705
|
+
"--pay-in-credits", action="store_true", help="Pay in credits for registration"
|
702
706
|
)
|
703
707
|
register_coldkey_parser.add_argument(
|
704
|
-
"--expires-in",
|
705
|
-
|
708
|
+
"--expires-in",
|
709
|
+
type=int,
|
710
|
+
default=10,
|
711
|
+
help="Challenge expiration in blocks (default: 10)",
|
706
712
|
)
|
707
713
|
register_coldkey_parser.add_argument(
|
708
|
-
"--block-width",
|
709
|
-
|
714
|
+
"--block-width",
|
715
|
+
choices=["u32", "u64"],
|
716
|
+
default="u32",
|
717
|
+
help="Block number width (default: u32)",
|
710
718
|
)
|
711
719
|
register_coldkey_parser.add_argument(
|
712
|
-
"--domain",
|
713
|
-
|
720
|
+
"--domain",
|
721
|
+
default="HIPPIUS::REGISTER::v1",
|
722
|
+
help="Domain for challenge (default: HIPPIUS::REGISTER::v1)",
|
714
723
|
)
|
715
724
|
register_coldkey_parser.add_argument(
|
716
725
|
"--nonce-hex", help="32-byte hex nonce (optional, random if not provided)"
|
717
726
|
)
|
718
727
|
register_coldkey_parser.add_argument(
|
719
|
-
"--dry-run",
|
720
|
-
|
728
|
+
"--dry-run",
|
729
|
+
action="store_true",
|
730
|
+
help="Do not submit extrinsic; just print payload",
|
721
731
|
)
|
722
732
|
|
723
733
|
# Register hotkey command
|
724
734
|
register_hotkey_parser = miner_subparsers.add_parser(
|
725
|
-
"register-hotkey",
|
735
|
+
"register-hotkey",
|
736
|
+
help="Register a node with hotkey (current account becomes hotkey)",
|
726
737
|
)
|
727
|
-
|
738
|
+
|
728
739
|
# Required arguments for register-hotkey
|
729
740
|
register_hotkey_parser.add_argument(
|
730
741
|
"--coldkey", required=True, help="Coldkey SS58 address"
|
@@ -733,49 +744,60 @@ def add_miner_commands(subparsers):
|
|
733
744
|
"--node-id", required=True, help="Your main node_id (libp2p peer ID)"
|
734
745
|
)
|
735
746
|
register_hotkey_parser.add_argument(
|
736
|
-
"--node-priv-hex",
|
747
|
+
"--node-priv-hex",
|
748
|
+
required=True,
|
749
|
+
help="Main libp2p ed25519 private key hex (32/64B)",
|
737
750
|
)
|
738
751
|
register_hotkey_parser.add_argument(
|
739
|
-
"--node-type",
|
752
|
+
"--node-type",
|
753
|
+
required=True,
|
740
754
|
choices=["StorageMiner", "Validator", "ComputeMiner", "StorageS3", "GpuMiner"],
|
741
|
-
help="Type of miner node"
|
755
|
+
help="Type of miner node",
|
742
756
|
)
|
743
|
-
|
757
|
+
|
744
758
|
# IPFS configuration (one required)
|
745
|
-
ipfs_group_hotkey = register_hotkey_parser.add_mutually_exclusive_group(
|
759
|
+
ipfs_group_hotkey = register_hotkey_parser.add_mutually_exclusive_group(
|
760
|
+
required=True
|
761
|
+
)
|
746
762
|
ipfs_group_hotkey.add_argument(
|
747
763
|
"--ipfs-config", help="Path to IPFS config file (e.g. ~/.ipfs/config)"
|
748
764
|
)
|
749
765
|
ipfs_group_hotkey.add_argument(
|
750
|
-
"--ipfs-priv-b64",
|
766
|
+
"--ipfs-priv-b64",
|
767
|
+
help="IPFS Identity.PrivKey base64 if not using --ipfs-config",
|
751
768
|
)
|
752
|
-
|
769
|
+
|
753
770
|
# Optional arguments
|
754
771
|
register_hotkey_parser.add_argument(
|
755
772
|
"--ipfs-peer-id", help="Optional override IPFS PeerID"
|
756
773
|
)
|
757
774
|
register_hotkey_parser.add_argument(
|
758
|
-
"--pay-in-credits", action="store_true",
|
759
|
-
help="Pay in credits for registration"
|
775
|
+
"--pay-in-credits", action="store_true", help="Pay in credits for registration"
|
760
776
|
)
|
761
777
|
register_hotkey_parser.add_argument(
|
762
|
-
"--expires-in",
|
763
|
-
|
778
|
+
"--expires-in",
|
779
|
+
type=int,
|
780
|
+
default=10,
|
781
|
+
help="Challenge expiration in blocks (default: 10)",
|
764
782
|
)
|
765
783
|
register_hotkey_parser.add_argument(
|
766
|
-
"--block-width",
|
767
|
-
|
784
|
+
"--block-width",
|
785
|
+
choices=["u32", "u64"],
|
786
|
+
default="u32",
|
787
|
+
help="Block number width (default: u32)",
|
768
788
|
)
|
769
789
|
register_hotkey_parser.add_argument(
|
770
|
-
"--domain",
|
771
|
-
|
790
|
+
"--domain",
|
791
|
+
default="HIPPIUS::REGISTER::v1",
|
792
|
+
help="Domain for challenge (default: HIPPIUS::REGISTER::v1)",
|
772
793
|
)
|
773
794
|
register_hotkey_parser.add_argument(
|
774
795
|
"--nonce-hex", help="32-byte hex nonce (optional, random if not provided)"
|
775
796
|
)
|
776
797
|
register_hotkey_parser.add_argument(
|
777
|
-
"--dry-run",
|
778
|
-
|
798
|
+
"--dry-run",
|
799
|
+
action="store_true",
|
800
|
+
help="Do not submit extrinsic; just print payload",
|
779
801
|
)
|
780
802
|
|
781
803
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|