Loading vLEI.wiki
Fetching knowledge base...
Fetching knowledge base...
This comprehensive explanation has been generated from 5 GitHub source documents. All source documents are searchable here.
Last updated: September 21, 2025
This content is meant to be consumed by AI agents via MCP. Click here to get the MCP configuration.
Note: In rare cases it may contain LLM hallucinations.
For authoritative documentation, please consult the official GLEIF vLEI trainings and the ToIP Glossary.
The most compact form of an ACDC (Authentic Chained Data Container) for a given disclosure level, containing SAIDs (Self-Addressing Identifiers) for undisclosed sections and expanded content for disclosed sections, optimizing the balance between data compression and selective revelation.
The most-compact form represents an optimal compression state of an ACDC (Authentic Chained Data Container) for a specific graduated disclosure level. Formally, given an ACDC A with disclosure level D, the most-compact form MC(A,D) is defined as:
MC(A,D) = {
field_i: SAID(section_i) if field_i ∉ D
field_i: expand(section_i) if field_i ∈ D
}
Where SAID(section_i) is the Self-Addressing Identifier of the undisclosed section, and expand(section_i) is the fully expanded content of the disclosed section.
The most-compact form operates on ACDC's standardized field structure with precise ordering:
Top-level field ordering: [v, d, u, i, rd, s, a, A, e, r]
Required Fields:
v (Version String): 24-character protocol identifier (e.g., "ACDC10JSON00011c_")d (Digest/SAID): 44-character Base64 self-referential cryptographic digesti (Issuer AID): Variable-length Autonomic Identifier of issuing authoritys (Schema): Either SAID reference or embedded JSON SchemaOptional Sections:
u (UUID): 24-character high-entropy nonce for privacy protectionrd (Registry Digest): SAID reference to TEL (Transaction Event Log)a (Attribute): Partially disclosable attribute sectionA (Attribute Aggregate): Selectively disclosable attribute sectione (Edge): Graph relationship references to other ACDCsr (Rule): Ricardian contract terms and conditionsCanonical JSON Ordering: The most critical implementation detail is ensuring consistent JSON canonicalization. Different JSON libraries may produce different string representations for the same data structure.
# WRONG - may produce inconsistent results
json.dumps(data)
# CORRECT - ensures consistent ordering
json.dumps(data, separators=(',', ':'), sort_keys=True, ensure_ascii=False)
Character Encoding: Always use UTF-8 encoding when computing SAIDs. Other encodings will produce different hash values.
# WRONG
hash_input = json_string.encode() # Uses system default encoding
# CORRECT
hash_input = json_string.encode('utf-8')
SAID Caching Strategy: Implement multi-level caching for computed SAIDs to avoid expensive recomputation:
class SAIDCache:
def __init__(self):
self.memory_cache = {} # L1: In-memory cache
self.disk_cache = {} # L2: Persistent cache
def get_or_compute_said(self, content):
content_hash = hash(json.dumps(content, sort_keys=True))
# Check L1 cache
if content_hash in self.memory_cache:
return self.memory_cache[content_hash]
# Check L2 cache
if content_hash in self.disk_cache:
said = self.disk_cache[content_hash]
self.memory_cache[content_hash] = said
return said
# Compute and cache
said = compute_said(content)
self.memory_cache[content_hash] = said
self.disk_cache[content_hash] = said
return said
Lazy Section Loading: For large ACDCs, implement lazy loading of sections:
class LazyACDC:
def __init__(self, acdc_data):
self.core_fields = {k: v for k, v in acdc_data.items()
if k in ['v', 'd', 'i']}
self.section_saids = {k: v for k, v in acdc_data.items()
if k not in ['v', 'd', 'i'] and isinstance(v, str)}
self._loaded_sections = {}
def get_section(self, field_name):
if field_name in self._loaded_sections:
return self._loaded_sections[field_name]
if field_name in self.section_saids:
section_data = self.resolve_said(self.section_saids[field_name])
self._loaded_sections[field_name] = section_data
return section_data
return None
: Always verify SAIDs when expanding sections:
The most-compact form uses a depth-first SAID computation algorithm ensuring deterministic digest calculation:
def compute_most_compact_said(acdc_data, disclosure_level):
# Step 1: Create working copy
compact_form = deepcopy(acdc_data)
# Step 2: Replace undisclosed sections with SAIDs
for field, section in compact_form.items():
if field not in disclosure_level:
if isinstance(section, dict):
compact_form[field] = compute_said(section)
# Step 3: Compute SAID of compact form
compact_form['d'] = '' # Clear self-referential field
canonical_json = serialize_canonical(compact_form)
digest = blake3_256(canonical_json.encode('utf-8'))
return base64_url_safe_encode(digest)
The most-compact form operates within a graduated disclosure state machine:
States:
- FULLY_COMPACT: All sections replaced with SAIDs
- MOST_COMPACT_L1: Level 1 disclosure (e.g., schema + metadata)
- MOST_COMPACT_L2: Level 2 disclosure (+ basic attributes)
- MOST_COMPACT_LN: Level N disclosure
- FULLY_EXPANDED: All sections expanded
Transitions:
- expand(section): MOST_COMPACT_Li → MOST_COMPACT_Li+1
- compact(section): MOST_COMPACT_Li → MOST_COMPACT_Li-1
- verify(SAID): Validate section integrity against SAID
The most-compact form integrates with IPEX (Issuance and Presentation Exchange) protocol:
Disclosee → Discloser: apply(schema_SAID, attribute_labels[])
Discloser → Disclosee: offer(most_compact_metadata)
Disclosee → Discloser: agree(signature_on_offer)
Discloser → Disclosee: grant(most_compact_with_disclosure)
Disclosee → Discloser: admit(signature_on_grant)
The most-compact form leverages SAID's cryptographic properties:
When an issuer signs any ACDC variant, the signature creates a cryptographic commitment to top-level section fields:
Commitment = Sign(PrivateKey, {
v: version_string,
d: acdc_said,
i: issuer_aid,
s: schema_said_or_content,
a: attribute_said_or_content,
...
})
This commitment remains valid across all disclosure levels because:
The most-compact form must comply with CESR (Composable Event Streaming Representation) encoding:
Most-compact forms must validate against their referenced schemas:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"v": {"type": "string", "pattern": "^ACDC10[A-Z]{4}[0-9a-f]{6}_$"},
"d": {"type": "string", "pattern": "^[A-Za-z0-9_-]{44}$"},
"i": {"type": "string"},
"s": {"oneOf": [
{"type": "string", "pattern": "^[A-Za-z0-9_-]{44}$"},
{"type": "object"}
]}
},
"required": ["v", "d", "i", "s"]
}
For high-performance implementations, most-compact forms should use memory-efficient layouts:
struct MostCompactACDC {
char version[25]; // 24 chars + null terminator
char digest[45]; // 44 chars + null terminator
char issuer_aid[256]; // Variable length, max 255
uint8_t disclosure_bitmap; // Bit flags for disclosed sections
void* sections[8]; // Pointers to section data or SAIDs
size_t section_sizes[8]; // Size of each section
};
The most-compact form exists within a hierarchy of ACDC variants:
fully-compact ⊂ most-compact ⊂ fully-expanded
where:
- fully-compact: All sections are SAIDs
- most-compact: Optimal mix of SAIDs and expanded content
- fully-expanded: All sections are expanded content
Most-compact ACDCs integrate with KERI components:
most-compact ACDC
├── SAID computation (BLAKE3/SHA3)
├── CESR encoding/decoding
├── JSON Schema validation
├── KERI AID resolution
├── TEL registry lookup
└── IPEX protocol messaging
Typical memory usage for most-compact ACDCs:
Base ACDC structure: ~200 bytes
SAID references (8 max): ~352 bytes (44 bytes × 8)
Expanded sections: Variable (typically 1KB - 10KB)
Total typical range: 500 bytes - 15KB
Most-compact forms optimize network transmission:
Operation | Time (μs) | Memory (KB)
------------------------|-----------|------------
SAID computation | 15-25 | 2-4
Disclosure level change | 5-10 | 1-2
Schema validation | 50-100 | 5-10
CESR encoding | 10-20 | 1-3
JSON serialization | 20-40 | 3-6
Most-compact forms must detect and handle circular SAID references:
def detect_circular_references(acdc, visited=None):
if visited is None:
visited = set()
current_said = acdc.get('d')
if current_said in visited:
raise CircularReferenceError(f"Circular reference detected: {current_said}")
visited.add(current_said)
# Check all SAID references in sections
for section in acdc.values():
if is_said_reference(section):
referenced_acdc = resolve_said(section)
detect_circular_references(referenced_acdc, visited.copy())
When disclosed content doesn't match its SAID:
def verify_section_integrity(section_content, expected_said):
computed_said = compute_said(section_content)
if computed_said != expected_said:
# Attempt recovery strategies:
# 1. Canonical JSON normalization
# 2. Character encoding correction
# 3. Schema-guided reconstruction
raise SAIDMismatchError(
f"Expected: {expected_said}, Got: {computed_said}"
)
Most-compact forms must handle schema version changes:
def handle_schema_evolution(acdc, target_schema_version):
current_version = extract_schema_version(acdc)
if current_version != target_schema_version:
migration_path = find_migration_path(
current_version, target_schema_version
)
return apply_migrations(acdc, migration_path)
return acdc
Most-compact ACDCs support various deployment patterns:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Edge Cache │ │ ACDC Registry │ │ Schema Store │
│ │ │ │ │ │
│ - Most-compact │◄──►│ - Full ACDCs │◄──►│ - JSON Schemas │
│ - Fast lookup │ │ - SAID index │ │ - Version mgmt │
│ - CDN ready │ │ - TEL anchored │ │ - Validation │
└─────────────────┘ └─────────────────┘ └─────────────────┘
Key metrics for most-compact ACDC systems:
metrics:
performance:
- said_computation_latency_p99
- disclosure_change_duration
- schema_validation_errors
- memory_usage_per_acdc
security:
- said_mismatch_incidents
- circular_reference_detections
- invalid_signature_attempts
- schema_validation_failures
business:
- disclosure_level_distribution
- acdc_size_histogram
- cache_hit_ratios
- network_bandwidth_savings
# Daily SAID index optimization
crontab -e
0 2 * * * /usr/local/bin/optimize-said-index --compact --verify
# Weekly integrity verification
0 3 * * 0 /usr/local/bin/verify-acdc-integrity --full-scan
# SAID mismatch recovery procedure
1. Identify affected ACDCs: grep "SAIDMismatchError" /var/log/acdc/*.log
2. Isolate corrupted entries: acdc-tool isolate --said-list corrupted.txt
3. Rebuild from source: acdc-tool rebuild --source-tel --verify-all
4. Validate integrity: acdc-tool verify --deep-check --report
kubernetes_deployment:
replicas: 10
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
autoscaling:
min_replicas: 3
max_replicas: 50
target_cpu_utilization: 70
target_memory_utilization: 80
# Multi-tier caching for most-compact ACDCs
class ACDCCache:
def __init__(self):
self.l1_cache = LRUCache(maxsize=1000) # In-memory
self.l2_cache = RedisCache(ttl=3600) # Distributed
self.l3_cache = S3Cache(bucket="acdc-cold") # Cold storage
def get_most_compact(self, said, disclosure_level):
cache_key = f"{said}:{hash(disclosure_level)}"
# L1 cache check
if result := self.l1_cache.get(cache_key):
return result
# L2 cache check
if result := self.l2_cache.get(cache_key):
self.l1_cache.set(cache_key, result)
return result
# L3 cache check
if result := self.l3_cache.get(cache_key):
self.l2_cache.set(cache_key, result)
self.l1_cache.set(cache_key, result)
return result
# Cache miss - compute and store
result = self.compute_most_compact(said, disclosure_level)
self.store_all_tiers(cache_key, result)
return result
def verify_and_expand_section(said, section_data):
computed_said = compute_said(section_data)
if computed_said != said:
raise SecurityError(f"SAID mismatch: expected {said}, got {computed_said}")
return section_data
Disclosure Level Validation: Validate that requested disclosure levels are authorized:
def validate_disclosure_request(acdc, requested_fields, requester_aid):
# Check if requester is authorized for requested disclosure level
authorized_fields = get_authorized_fields(acdc, requester_aid)
unauthorized = set(requested_fields) - set(authorized_fields)
if unauthorized:
raise AuthorizationError(f"Unauthorized fields: {unauthorized}")
Memory Safety: Implement bounds checking for large ACDCs:
MAX_ACDC_SIZE = 10 * 1024 * 1024 # 10MB limit
MAX_SECTION_COUNT = 100
def validate_acdc_size(acdc_data):
serialized = json.dumps(acdc_data)
if len(serialized.encode('utf-8')) > MAX_ACDC_SIZE:
raise ValueError("ACDC exceeds maximum size limit")
if len(acdc_data) > MAX_SECTION_COUNT:
raise ValueError("ACDC exceeds maximum section count")
Property-Based Testing: Use property-based testing to verify SAID computation consistency:
import hypothesis
from hypothesis import strategies as st
@hypothesis.given(
acdc_data=st.dictionaries(
keys=st.sampled_from(['v', 'd', 'i', 's', 'a', 'e', 'r']),
values=st.one_of(st.text(), st.dictionaries(st.text(), st.text()))
)
)
def test_said_computation_consistency(acdc_data):
# Ensure SAID computation is deterministic
said1 = compute_said(acdc_data)
said2 = compute_said(acdc_data)
assert said1 == said2
# Ensure different data produces different SAIDs
modified_data = acdc_data.copy()
modified_data['test_field'] = 'test_value'
said3 = compute_said(modified_data)
if acdc_data != modified_data:
assert said1 != said3
Round-Trip Testing: Verify that expansion and compaction are inverse operations:
def test_expansion_compaction_roundtrip():
original_acdc = create_test_acdc()
disclosure_level = {'s', 'a'}
# Compact then expand
most_compact = compute_most_compact(original_acdc, disclosure_level)
expanded = expand_acdc(most_compact, disclosure_level)
# Should match original for disclosed fields
for field in disclosure_level:
assert expanded[field] == original_acdc[field]
Concurrency Testing: Test thread safety for caching mechanisms:
import threading
import concurrent.futures
def test_concurrent_said_computation():
acdc_data = create_large_test_acdc()
results = []
def compute_said_worker():
return compute_said(acdc_data)
# Run multiple threads computing the same SAID
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
futures = [executor.submit(compute_said_worker) for _ in range(100)]
results = [future.result() for future in futures]
# All results should be identical
assert all(result == results[0] for result in results)