blockmachine 0.8.3__tar.gz → 0.9.0__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.
- {blockmachine-0.8.3 → blockmachine-0.9.0}/PKG-INFO +1 -1
- {blockmachine-0.8.3 → blockmachine-0.9.0}/blockmachine.egg-info/PKG-INFO +1 -1
- {blockmachine-0.8.3 → blockmachine-0.9.0}/commands/auth.py +2 -2
- {blockmachine-0.8.3 → blockmachine-0.9.0}/commands/miner.py +51 -4
- {blockmachine-0.8.3 → blockmachine-0.9.0}/commands/validator.py +1 -1
- {blockmachine-0.8.3 → blockmachine-0.9.0}/config.py +1 -1
- {blockmachine-0.8.3 → blockmachine-0.9.0}/pyproject.toml +1 -1
- {blockmachine-0.8.3 → blockmachine-0.9.0}/settings.py +7 -1
- {blockmachine-0.8.3 → blockmachine-0.9.0}/tests/test_cli_config.py +3 -2
- {blockmachine-0.8.3 → blockmachine-0.9.0}/__init__.py +0 -0
- {blockmachine-0.8.3 → blockmachine-0.9.0}/auth_config.py +0 -0
- {blockmachine-0.8.3 → blockmachine-0.9.0}/blockmachine.egg-info/SOURCES.txt +0 -0
- {blockmachine-0.8.3 → blockmachine-0.9.0}/blockmachine.egg-info/dependency_links.txt +0 -0
- {blockmachine-0.8.3 → blockmachine-0.9.0}/blockmachine.egg-info/entry_points.txt +0 -0
- {blockmachine-0.8.3 → blockmachine-0.9.0}/blockmachine.egg-info/requires.txt +0 -0
- {blockmachine-0.8.3 → blockmachine-0.9.0}/blockmachine.egg-info/top_level.txt +0 -0
- {blockmachine-0.8.3 → blockmachine-0.9.0}/client.py +0 -0
- {blockmachine-0.8.3 → blockmachine-0.9.0}/commands/__init__.py +0 -0
- {blockmachine-0.8.3 → blockmachine-0.9.0}/commands/leaderboard.py +0 -0
- {blockmachine-0.8.3 → blockmachine-0.9.0}/endpoints.py +0 -0
- {blockmachine-0.8.3 → blockmachine-0.9.0}/main.py +0 -0
- {blockmachine-0.8.3 → blockmachine-0.9.0}/setup.cfg +0 -0
- {blockmachine-0.8.3 → blockmachine-0.9.0}/testing.py +0 -0
- {blockmachine-0.8.3 → blockmachine-0.9.0}/tests/test_cli_endpoints_and_testing.py +0 -0
- {blockmachine-0.8.3 → blockmachine-0.9.0}/tests/test_leaderboard_cli.py +0 -0
- {blockmachine-0.8.3 → blockmachine-0.9.0}/utils.py +0 -0
|
@@ -26,7 +26,7 @@ def device_login(
|
|
|
26
26
|
|
|
27
27
|
Raises typer.Exit(1) on failure.
|
|
28
28
|
"""
|
|
29
|
-
client_id = client_id or settings.
|
|
29
|
+
client_id = client_id or settings.client_id()
|
|
30
30
|
auth_url = auth_url or settings.auth_url()
|
|
31
31
|
|
|
32
32
|
try:
|
|
@@ -157,7 +157,7 @@ def save_token(
|
|
|
157
157
|
|
|
158
158
|
config = load_config()
|
|
159
159
|
config.set_role(role)
|
|
160
|
-
config.client_id = client_id or settings.
|
|
160
|
+
config.client_id = client_id or settings.client_id()
|
|
161
161
|
config.auth_url = auth_url or settings.auth_url()
|
|
162
162
|
config.api_url = api_url or settings.api_url()
|
|
163
163
|
config.access_token = access_token
|
|
@@ -457,13 +457,17 @@ def update(
|
|
|
457
457
|
alias: str = typer.Argument(None, help="Node alias or ID"),
|
|
458
458
|
new_alias: str = typer.Option(None, "--alias", "-a", help="New alias"),
|
|
459
459
|
endpoint: str = typer.Option(None, "--endpoint", "-e", help="New endpoint"),
|
|
460
|
+
repin: bool = typer.Option(
|
|
461
|
+
False, "--repin", help="Re-detect and update TLS cert fingerprint"
|
|
462
|
+
),
|
|
460
463
|
) -> None:
|
|
461
|
-
"""Update a node's alias or
|
|
464
|
+
"""Update a node's alias, endpoint, or TLS fingerprint."""
|
|
462
465
|
alias = _get_alias(alias)
|
|
463
466
|
|
|
464
|
-
if not new_alias and not endpoint:
|
|
467
|
+
if not new_alias and not endpoint and not repin:
|
|
465
468
|
console.print(
|
|
466
|
-
"[yellow]Nothing to update.
|
|
469
|
+
"[yellow]Nothing to update."
|
|
470
|
+
" Specify --alias, --endpoint, or --repin[/yellow]"
|
|
467
471
|
)
|
|
468
472
|
return
|
|
469
473
|
|
|
@@ -476,6 +480,32 @@ def update(
|
|
|
476
480
|
|
|
477
481
|
with RegistryClient(config) as client:
|
|
478
482
|
node_id = _resolve_node(client, alias)
|
|
483
|
+
|
|
484
|
+
if repin:
|
|
485
|
+
node_resp = client.get(f"/nodes/{node_id}")
|
|
486
|
+
if node_resp.status_code != 200:
|
|
487
|
+
console.print(f"[red]Error fetching node:[/red] {node_resp.text}")
|
|
488
|
+
raise typer.Exit(1)
|
|
489
|
+
node_endpoint = endpoint or node_resp.json()["endpoint"]
|
|
490
|
+
if not is_ip_endpoint(node_endpoint):
|
|
491
|
+
console.print(
|
|
492
|
+
"[yellow]--repin ignored:"
|
|
493
|
+
" only applies to IP-based endpoints[/yellow]"
|
|
494
|
+
)
|
|
495
|
+
else:
|
|
496
|
+
fp = get_cert_fingerprint(node_endpoint)
|
|
497
|
+
if fp:
|
|
498
|
+
update_data["cert_fingerprint"] = fp
|
|
499
|
+
console.print(f"[dim]New TLS fingerprint: {fp}[/dim]")
|
|
500
|
+
else:
|
|
501
|
+
console.print(
|
|
502
|
+
"[red]Could not fetch TLS certificate from endpoint[/red]"
|
|
503
|
+
)
|
|
504
|
+
raise typer.Exit(1)
|
|
505
|
+
|
|
506
|
+
if not update_data:
|
|
507
|
+
return
|
|
508
|
+
|
|
479
509
|
response = client.patch(f"/nodes/{node_id}", json=update_data)
|
|
480
510
|
|
|
481
511
|
if response.status_code == 200:
|
|
@@ -522,6 +552,7 @@ def test(
|
|
|
522
552
|
automatically. Use --endpoint and --secret for pre-registration
|
|
523
553
|
testing.
|
|
524
554
|
"""
|
|
555
|
+
stored_fingerprint: Optional[str] = None
|
|
525
556
|
if not endpoint:
|
|
526
557
|
alias = _get_alias(alias)
|
|
527
558
|
config = load_config()
|
|
@@ -533,6 +564,7 @@ def test(
|
|
|
533
564
|
raise typer.Exit(1)
|
|
534
565
|
node = response.json()
|
|
535
566
|
endpoint = node["endpoint"]
|
|
567
|
+
stored_fingerprint = node.get("cert_fingerprint")
|
|
536
568
|
if not secret:
|
|
537
569
|
secret = _fetch_active_secret(client, node_id)
|
|
538
570
|
console.print(f"[bold]Alias:[/bold] {alias}")
|
|
@@ -555,12 +587,27 @@ def test(
|
|
|
555
587
|
if tls_ok:
|
|
556
588
|
is_ip = is_ip_endpoint(endpoint)
|
|
557
589
|
mode = "pinned" if is_ip else "CA-verified"
|
|
558
|
-
fp_short = fingerprint
|
|
590
|
+
fp_short = _truncate(fingerprint, 16) if fingerprint else "none"
|
|
559
591
|
console.print(f"[green]OK[/green] ({mode}, {fp_short})")
|
|
560
592
|
else:
|
|
561
593
|
console.print(f"[red]FAIL[/red] {tls_msg}")
|
|
562
594
|
all_ok = False
|
|
563
595
|
|
|
596
|
+
if stored_fingerprint and fingerprint:
|
|
597
|
+
console.print("Cert pinning... ", end="")
|
|
598
|
+
if stored_fingerprint == fingerprint:
|
|
599
|
+
console.print("[green]OK[/green] (matches registry)")
|
|
600
|
+
else:
|
|
601
|
+
console.print("[red]MISMATCH[/red]")
|
|
602
|
+
console.print(
|
|
603
|
+
f"[yellow] ↳ Registry: {_truncate(stored_fingerprint, 16)}[/yellow]"
|
|
604
|
+
)
|
|
605
|
+
console.print(
|
|
606
|
+
f"[yellow] ↳ Live: {_truncate(fingerprint, 16)}[/yellow]"
|
|
607
|
+
)
|
|
608
|
+
console.print("[yellow] ↳ Run 'bm miner update --repin' to fix[/yellow]")
|
|
609
|
+
all_ok = False
|
|
610
|
+
|
|
564
611
|
# 2. Health
|
|
565
612
|
console.print("Health check... ", end="")
|
|
566
613
|
health_ok, health_msg = test_health(hostname)
|
|
@@ -20,7 +20,7 @@ def login(
|
|
|
20
20
|
),
|
|
21
21
|
) -> None:
|
|
22
22
|
"""Login with validator scopes for the verification gateway."""
|
|
23
|
-
resolved_client_id = client_id or settings.
|
|
23
|
+
resolved_client_id = client_id or settings.client_id()
|
|
24
24
|
resolved_auth_url = auth_url or settings.auth_url()
|
|
25
25
|
|
|
26
26
|
token_data = device_login(
|
|
@@ -126,7 +126,7 @@ class CLIConfig:
|
|
|
126
126
|
|
|
127
127
|
@property
|
|
128
128
|
def client_id(self) -> str:
|
|
129
|
-
return self._net().client_id or settings.
|
|
129
|
+
return self._net().client_id or settings.client_id()
|
|
130
130
|
|
|
131
131
|
@client_id.setter
|
|
132
132
|
def client_id(self, value: Optional[str]) -> None:
|
|
@@ -15,18 +15,21 @@ class NetworkConfig:
|
|
|
15
15
|
auth_url: str
|
|
16
16
|
api_url: str
|
|
17
17
|
netuid: int
|
|
18
|
+
client_id: str
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
MAINNET = NetworkConfig(
|
|
21
22
|
auth_url="https://auth.taostats.io",
|
|
22
23
|
api_url="https://api.blockmachine.io",
|
|
23
24
|
netuid=19,
|
|
25
|
+
client_id="35cc50f5-6bf5-432b-8892-84c3b0e856b2",
|
|
24
26
|
)
|
|
25
27
|
|
|
26
28
|
TESTNET = NetworkConfig(
|
|
27
29
|
auth_url="https://test-auth.taostats.io",
|
|
28
30
|
api_url="https://testnet-registry.blockmachine.io",
|
|
29
31
|
netuid=417,
|
|
32
|
+
client_id="07f5c729-5ca7-412a-b5e7-4966e132548e",
|
|
30
33
|
)
|
|
31
34
|
|
|
32
35
|
# Active network — set by --testnet flag via main.py callback
|
|
@@ -57,10 +60,13 @@ def netuid() -> int:
|
|
|
57
60
|
return _network.netuid
|
|
58
61
|
|
|
59
62
|
|
|
60
|
-
CLIENT_ID = os.environ.get("BM_CLIENT_ID", "07f5c729-5ca7-412a-b5e7-4966e132548e")
|
|
61
63
|
AUDIENCE = "bittensor-apps"
|
|
62
64
|
|
|
63
65
|
|
|
66
|
+
def client_id() -> str:
|
|
67
|
+
return os.environ.get("BM_CLIENT_ID", _network.client_id)
|
|
68
|
+
|
|
69
|
+
|
|
64
70
|
def jwks_uri() -> str:
|
|
65
71
|
return f"{auth_url()}/.well-known/jwks.json"
|
|
66
72
|
|
|
@@ -71,7 +71,7 @@ class TestSettings:
|
|
|
71
71
|
s.set_network(s.MAINNET)
|
|
72
72
|
assert s.auth_url() == "https://auth.taostats.io"
|
|
73
73
|
assert s.api_url() == "https://api.blockmachine.io"
|
|
74
|
-
assert s.
|
|
74
|
+
assert s.client_id() == "35cc50f5-6bf5-432b-8892-84c3b0e856b2"
|
|
75
75
|
assert s.jwks_uri() == ("https://auth.taostats.io/.well-known/jwks.json")
|
|
76
76
|
assert s.miner_scopes() == ["subnet:19:miner"]
|
|
77
77
|
assert s.validator_scopes() == ["subnet:19:validator"]
|
|
@@ -101,7 +101,8 @@ class TestSettings:
|
|
|
101
101
|
|
|
102
102
|
assert s.auth_url() == "https://custom-auth.example.com"
|
|
103
103
|
assert s.api_url() == "https://custom-api.example.com"
|
|
104
|
-
|
|
104
|
+
s.set_network(s.MAINNET)
|
|
105
|
+
assert s.client_id() == "custom-client-id"
|
|
105
106
|
assert s.jwks_uri() == (
|
|
106
107
|
"https://custom-auth.example.com/.well-known/jwks.json"
|
|
107
108
|
)
|
|
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
|