feat: DGR-003 - Define exact Artifact and runtime recipe identity
This commit is contained in:
270
tests/test_runtime_recipe_identity.py
Normal file
270
tests/test_runtime_recipe_identity.py
Normal file
@@ -0,0 +1,270 @@
|
||||
"""Deterministic DGR-003 identity and tracker-admission conformance tests."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import replace
|
||||
import json
|
||||
from pathlib import Path
|
||||
import time
|
||||
|
||||
import pytest
|
||||
|
||||
from meshnet_node.runtime_recipe import (
|
||||
ArtifactIdentity,
|
||||
CompatibilityFingerprint,
|
||||
DerivativeBinding,
|
||||
RecipeIdentityError,
|
||||
RuntimeRecipe,
|
||||
ShardIdentity,
|
||||
check_handshake,
|
||||
check_route,
|
||||
handshake_error,
|
||||
)
|
||||
from meshnet_tracker.capability import (
|
||||
STATE_ADMITTED,
|
||||
STATE_FINGERPRINT_MISMATCH,
|
||||
STATE_MODEL_MISMATCH,
|
||||
STATE_RECIPE_MISMATCH,
|
||||
STATE_UNCERTIFIED,
|
||||
evaluate_report,
|
||||
)
|
||||
from meshnet_tracker.server import TrackerServer, _capability_from_registration
|
||||
from meshnet_tracker.recipe import (
|
||||
CertificationLedger,
|
||||
DistributedForwardEvidence,
|
||||
parse_identity,
|
||||
)
|
||||
|
||||
|
||||
def _digest(char: str) -> str:
|
||||
return char * 64
|
||||
|
||||
|
||||
def _identity(start: int = 0, end: int = 4, **recipe_changes: object) -> ShardIdentity:
|
||||
recipe_fields: dict[str, object] = {
|
||||
"weight_quantization": "Q4_K_M",
|
||||
"activation_dtype": "bfloat16",
|
||||
"compute_dtype": "float32",
|
||||
"kv_dtype": "q8_0",
|
||||
"kv_layout": "paged-v1",
|
||||
"tokenizer_revision": "0123456789abcdef",
|
||||
"architecture_adapter": "llama/range-v1",
|
||||
"backend_id": "llama.cpp",
|
||||
"runtime_version": "llama.cpp@deadbeef+meshnet.1",
|
||||
"recipe_id": "example-gguf",
|
||||
"recipe_version": "1",
|
||||
"catalogue_version": "2026.07.1",
|
||||
}
|
||||
recipe_fields.update(recipe_changes)
|
||||
recipe = RuntimeRecipe(**recipe_fields) # type: ignore[arg-type]
|
||||
return ShardIdentity(
|
||||
ArtifactIdentity(
|
||||
"example/model",
|
||||
"0123456789abcdef",
|
||||
_digest("a"),
|
||||
"dense-llama",
|
||||
_digest("b"),
|
||||
8,
|
||||
),
|
||||
recipe,
|
||||
start,
|
||||
end,
|
||||
)
|
||||
|
||||
|
||||
def _report(identity: ShardIdentity) -> dict:
|
||||
return {
|
||||
"schema_version": 1,
|
||||
"model": {"model_id": "example/model"},
|
||||
"shard": {"start": identity.shard_start, "end": identity.shard_end - 1},
|
||||
"recipe": identity.recipe.to_dict() | {
|
||||
"recipe_id": identity.recipe.recipe_id,
|
||||
"recipe_version": identity.recipe.recipe_version,
|
||||
"catalogue_version": identity.recipe.catalogue_version,
|
||||
},
|
||||
"backend": {"backend_id": "llama.cpp", "device": "test"},
|
||||
"status": "passed",
|
||||
"validated_at": 100.0,
|
||||
"duration_ms": 1,
|
||||
"diagnostics": [],
|
||||
"identity": identity.to_dict(),
|
||||
}
|
||||
|
||||
|
||||
def _evaluate(report: dict, **kwargs: object):
|
||||
return evaluate_report(
|
||||
report,
|
||||
model_matches=lambda model: model == "example/model",
|
||||
advertised_model="example/model",
|
||||
shard_start=0,
|
||||
shard_end=3,
|
||||
now=100.0,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
|
||||
def test_node_and_tracker_share_the_committed_canonical_fingerprint_vector():
|
||||
vector_path = Path(__file__).parent / "data" / "recipe_fingerprint_vectors.json"
|
||||
vector = json.loads(vector_path.read_text(encoding="utf-8"))["vectors"][0]
|
||||
expected = vector["fingerprint"]
|
||||
identity = ShardIdentity.from_dict(vector["identity"])
|
||||
|
||||
assert identity.fingerprint.to_dict() == expected
|
||||
assert parse_identity(vector["identity"]).fingerprint_dict() == expected
|
||||
assert (
|
||||
CompatibilityFingerprint.from_proto(identity.fingerprint.to_proto()).to_dict()
|
||||
== expected
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"axis,value",
|
||||
[
|
||||
("weight_quantization", "Q5_K_M"),
|
||||
("activation_dtype", "float16"),
|
||||
("compute_dtype", "float16"),
|
||||
("kv_dtype", "float16"),
|
||||
("kv_layout", "contiguous-v2"),
|
||||
("tokenizer_revision", "fedcba9876543210"),
|
||||
("architecture_adapter", "llama/range-v2"),
|
||||
("backend_id", "other-backend"),
|
||||
("runtime_version", "llama.cpp@other+meshnet.1"),
|
||||
("boundary_schema_version", 2),
|
||||
("protocol_schema_version", 2),
|
||||
],
|
||||
)
|
||||
def test_every_recipe_axis_changes_the_fingerprint_and_blocks_route(axis, value):
|
||||
left = _identity()
|
||||
right = _identity(4, 8, **{axis: value})
|
||||
|
||||
assert left.fingerprint.key != right.fingerprint.key
|
||||
assert check_route([left, right])
|
||||
|
||||
|
||||
def test_split_artifact_is_bound_to_exact_source_and_owned_range():
|
||||
source = _identity()
|
||||
split = ShardIdentity(
|
||||
ArtifactIdentity(
|
||||
"example/model",
|
||||
"0123456789abcdef",
|
||||
_digest("c"),
|
||||
"dense-llama",
|
||||
_digest("b"),
|
||||
8,
|
||||
DerivativeBinding(_digest("a"), 4, 8),
|
||||
),
|
||||
source.recipe,
|
||||
4,
|
||||
8,
|
||||
)
|
||||
assert source.fingerprint.matches(split.fingerprint)
|
||||
with pytest.raises(RecipeIdentityError):
|
||||
ShardIdentity(split.artifact, split.recipe, 3, 8)
|
||||
|
||||
|
||||
def test_declared_digest_mismatch_is_recomputed_and_rejected_not_authenticated():
|
||||
report = _report(_identity())
|
||||
report["identity"]["fingerprint"]["runtime_recipe_digest"] = _digest("f")
|
||||
|
||||
assert _evaluate(report).state == STATE_FINGERPRINT_MISMATCH
|
||||
|
||||
|
||||
def test_exact_recipe_registers_dark_until_tracker_certification():
|
||||
identity = _identity()
|
||||
report = _report(identity)
|
||||
ledger = CertificationLedger()
|
||||
|
||||
dark = _evaluate(report, ledger=ledger)
|
||||
assert dark.state == STATE_UNCERTIFIED
|
||||
# Unit fixtures cannot promote a recipe: this is the explicit trust boundary.
|
||||
with pytest.raises(ValueError, match="synthetic"):
|
||||
ledger.certify(
|
||||
parse_identity(identity.to_dict()),
|
||||
DistributedForwardEvidence(
|
||||
"session",
|
||||
1,
|
||||
("a", "b"),
|
||||
((0, 4), (4, 8)),
|
||||
1,
|
||||
8,
|
||||
identity.fingerprint.key,
|
||||
synthetic=True,
|
||||
),
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError, match="fingerprint does not match"):
|
||||
ledger.certify(
|
||||
parse_identity(identity.to_dict()),
|
||||
DistributedForwardEvidence(
|
||||
"session",
|
||||
1,
|
||||
("a", "b"),
|
||||
((0, 4), (4, 8)),
|
||||
1,
|
||||
8,
|
||||
(_digest("e"), _digest("f")),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def test_capability_identity_must_match_the_proof_labels():
|
||||
identity = _identity()
|
||||
|
||||
wrong_model = _report(identity)
|
||||
wrong_model["identity"]["artifact"]["artifact_id"] = "other/model"
|
||||
wrong_model["identity"]["fingerprint"] = None
|
||||
assert _evaluate(wrong_model).state == STATE_MODEL_MISMATCH
|
||||
|
||||
wrong_recipe = _report(identity)
|
||||
wrong_recipe["recipe"]["recipe_id"] = "other-recipe"
|
||||
assert _evaluate(wrong_recipe).state == STATE_RECIPE_MISMATCH
|
||||
|
||||
wrong_backend = _report(identity)
|
||||
wrong_backend["backend"]["backend_id"] = "other-backend"
|
||||
assert _evaluate(wrong_backend).state == STATE_RECIPE_MISMATCH
|
||||
|
||||
wrong_quantization = _report(identity)
|
||||
wrong_quantization["backend"]["quantization"] = "Q5_K_M"
|
||||
assert _evaluate(wrong_quantization).state == STATE_RECIPE_MISMATCH
|
||||
|
||||
|
||||
def test_tracker_server_owns_the_ledger_used_by_registration():
|
||||
identity = _identity()
|
||||
report = _report(identity)
|
||||
report["validated_at"] = time.time()
|
||||
payload = {"capability_report": report}
|
||||
tracker = TrackerServer()
|
||||
|
||||
def evaluate():
|
||||
return _capability_from_registration(
|
||||
payload,
|
||||
model="example/model",
|
||||
hf_repo=None,
|
||||
shard_start=0,
|
||||
shard_end=3,
|
||||
recipe_certifications=tracker._recipe_certifications,
|
||||
)
|
||||
|
||||
assert evaluate().state == STATE_UNCERTIFIED
|
||||
tracker._recipe_certifications.certify(
|
||||
parse_identity(identity.to_dict()),
|
||||
DistributedForwardEvidence(
|
||||
"session",
|
||||
1,
|
||||
("physical-a", "physical-b"),
|
||||
((0, 4), (4, 8)),
|
||||
1,
|
||||
8,
|
||||
identity.fingerprint.key,
|
||||
),
|
||||
)
|
||||
assert evaluate().state == STATE_ADMITTED
|
||||
|
||||
|
||||
def test_grpc_handshake_uses_the_dgr_002_fingerprint_and_fails_closed():
|
||||
local = _identity()
|
||||
remote = replace(local.fingerprint, runtime_recipe_digest=_digest("f")).to_proto()
|
||||
|
||||
mismatches = check_handshake(local, remote)
|
||||
assert mismatches
|
||||
assert handshake_error(mismatches).code != 0
|
||||
Reference in New Issue
Block a user