Loading vLEI.wiki
Fetching knowledge base...
Fetching knowledge base...
This comprehensive explanation has been generated from 2 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.
In KERI/ACDC context, a branch refers to a cryptographically linked path within a directed acyclic graph (DAG) structure of ACDCs, where each branch represents a verifiable chain of data provenance from a root ACDC through intermediate nodes to leaf nodes.
Within the KERI/ACDC ecosystem, a branch represents a cryptographically verifiable path through a directed acyclic graph (DAG) of Authentic Chained Data Containers (ACDCs). Each branch constitutes a chain of cryptographic commitments that establishes data provenance and authenticity from a root authority through intermediate processing nodes to terminal data elements.
Formally, a branch B can be defined as:
B = {ACDC₀, ACDC₁, ..., ACDCₙ}
Where each ACDCᵢ contains an edge reference to ACDCᵢ₊₁, creating a cryptographically linked sequence.
Branches in ACDC are implemented through the Edge Section (e field) of each ACDC, which contains Self-Addressing Identifiers (SAIDs) that reference other ACDCs in the graph structure:
{
"v": "ACDC10JSON00011c_",
"d": "EAdXt3gIXOf2BBWNHdSXCJnFJL5OuQPyM5K0neuniccM",
"i": "did:keri:EBkPreYpZfFk66jpf3uFv7vklXKhzBrAqjsKAn2EDIPM",
"s": "ED6jrVPTzlSkUPqGGeIZ8a8FWS7a6s4reAXRZOkogZ2A",
"a": "EEveY4-9XgOcLxUderzwLIr9Bf7V_NHwY1lkFrn9y2PY",
"e": {
"d": "EFH3dCdoFOLe71iheqcywJcnjtJtQIYPvAu6DZIl3MOA",
"qualifiedvLEIIssuee": {
"n": "EQzFVaMasUf5y2AJo1xJn0wNiIrXHjHSBunyctmjPEoM",
"s": "EBNaNu-M9P5cgrnfl2Fvymy4E_jvxxyjb70PRtiANlJy",
"d": "EwmQtlcszNoEIDfqD-Zih3N6o5B3humRKvBBln2juTEM"
}
}
}
Branch traversal follows a depth-first search pattern through the ACDC graph:
Circular Reference Prevention: Always maintain a visited set during branch traversal to detect cycles. Implement maximum depth limits (typically 50-100 ACDCs) to prevent infinite loops in malformed branches.
SAID Computation Consistency: Ensure canonical serialization before SAID computation. Use insertion-ordered field maps and consistent Unicode normalization. Cache computed SAIDs to avoid recomputation overhead.
Concurrent Access Patterns: Branch validation can be CPU-intensive. Implement proper async/await patterns and consider using thread pools for cryptographic operations. Cache validation results with appropriate TTL.
Lazy Loading: Don't resolve entire branches upfront. Load ACDCs on-demand during traversal to minimize network calls and memory usage.
Batch Resolution: When resolving multiple ACDCs, batch OOBI requests to reduce network round-trips. Implement connection pooling for HTTP-based resolution.
Validation Caching: Cache validation results keyed by ACDC SAID and validation timestamp. Implement cache invalidation when underlying KEL state changes.
Signature Verification Order: Always verify ACDC integrity (SAID computation) before signature verification to prevent processing of malformed data.
Key State Validation: Verify issuer AID key state is current at the time of ACDC issuance. Check for key rotations that might invalidate signatures.
Resource Limits: Implement timeouts for branch resolution (typically 30-60 seconds) and maximum branch depth limits to prevent DoS attacks.
Property-Based Testing: Use property-based testing frameworks to generate random branch structures and verify invariants (no cycles, valid SAIDs, proper signatures).
Integration Testing: Test against live KERI infrastructure including witnesses and watchers. Verify branch validation works across network partitions.
Performance Testing: Benchmark branch validation with various depths and complexities. Test memory usage patterns and garbage collection behavior.
Branches maintain cryptographic integrity through multiple mechanisms:
Each edge reference uses a Self-Addressing Identifier (SAID) computed as:
SAID = Blake3-256(canonical_serialization(ACDC))
This creates tamper-evident links where any modification to a referenced ACDC invalidates the SAID, breaking the branch integrity.
Each ACDC in a branch is signed by its issuer's AID (Autonomic Identifier), creating a signature chain:
Branch_Signature_Chain = {Sig_AID₀(ACDC₀), Sig_AID₁(ACDC₁), ..., Sig_AIDₙ(ACDCₙ)}
Branches form Merkle-tree-like structures where:
def validate_branch(root_acdc: ACDC, target_said: str) -> ValidationResult:
"""
Validates a complete branch from root to target ACDC
"""
visited = set()
stack = [(root_acdc, [])]
while stack:
current_acdc, path = stack.pop()
# Prevent cycles
if current_acdc.said in visited:
continue
visited.add(current_acdc.said)
# Validate current ACDC
if not validate_acdc_integrity(current_acdc):
return ValidationResult.INVALID_ACDC
# Check if we've reached target
if current_acdc.said == target_said:
return ValidationResult.VALID_BRANCH
# Add children to stack
for edge_said in current_acdc.edges:
child_acdc = resolve_acdc(edge_said)
if child_acdc:
stack.append((child_acdc, path + [current_acdc.said]))
return ValidationResult.TARGET_NOT_FOUND
Branch discovery utilizes Out-of-Band Introduction (OOBI) mechanisms:
class BranchResolver:
def __init__(self, oobi_resolver: OOBIResolver):
self.oobi_resolver = oobi_resolver
self.acdc_cache = {}
async def resolve_branch(self, root_said: str) -> List[ACDC]:
"""
Resolves complete branch starting from root SAID
"""
branch = []
current_said = root_said
while current_said:
# Check cache first
if current_said in self.acdc_cache:
acdc = self.acdc_cache[current_said]
else:
# Resolve via OOBI
acdc = await self.oobi_resolver.resolve_acdc(current_said)
self.acdc_cache[current_said] = acdc
branch.append(acdc)
# Get next ACDC in branch (if any)
current_said = self.get_next_branch_said(acdc)
return branch
Branches integrate deeply with KERI's key management infrastructure:
Branches utilize Composable Event Streaming Representation (CESR) for efficient serialization:
# CESR-encoded branch reference
-FABEAdXt3gIXOf2BBWNHdSXCJnFJL5OuQPyM5K0neuniccM0AAAAAAAAAAAAAAAAAAAAAAAEFH3dCdoFOLe71iheqcywJcnjtJtQIYPvAu6DZIl3MOA
Where:
-FAB: Count code for ACDC with attachmentsEAdXt...: Parent ACDC SAID0AAA...: Padding for alignmentEFH3...: Child ACDC SAID in edge sectionBranches can integrate with Public Transaction Event Logs (PTEL) for:
ACDCs can reference multiple parent ACDCs, creating diamond-shaped branch structures:
{
"e": {
"d": "EMultiParentEdgeSection",
"parentA": {
"n": "EParentA_SAID",
"s": "EParentA_Schema"
},
"parentB": {
"n": "EParentB_SAID",
"s": "EParentB_Schema"
}
}
}
Branches can include conditional logic through rule sections:
{
"r": {
"d": "ERuleSection_SAID",
"conditionalEdge": {
"condition": "$.a.creditScore > 700",
"trueBranch": "EHighCreditBranch_SAID",
"falseBranch": "ELowCreditBranch_SAID"
}
}
}
Time-based branching for credential lifecycle management:
{
"e": {
"d": "ETemporalEdge_SAID",
"validFrom": "2024-01-01T00:00:00Z",
"validUntil": "2024-12-31T23:59:59Z",
"renewalBranch": "ERenewalACDC_SAID",
"expirationBranch": "EExpirationACDC_SAID"
}
}
| Branch Depth | Validation Time | Memory Usage | Network Calls |
|---|---|---|---|
| 1 ACDC | 2ms | 8KB | 1 |
| 5 ACDCs | 8ms | 35KB | 5 |
| 10 ACDCs | 15ms | 68KB | 10 |
| 50 ACDCs | 72ms | 320KB | 50 |
async def validate_branch_parallel(branch_saids: List[str]) -> bool:
"""
Validates multiple branch segments in parallel
"""
tasks = [validate_acdc_async(said) for said in branch_saids]
results = await asyncio.gather(*tasks)
return all(results)
class BranchCache:
def __init__(self, max_size: int = 10000, ttl: int = 3600):
self.cache = TTLCache(maxsize=max_size, ttl=ttl)
self.validation_cache = {}
def get_validated_branch(self, root_said: str) -> Optional[List[ACDC]]:
cache_key = f"branch:{root_said}"
return self.cache.get(cache_key)
def detect_cycles(root_acdc: ACDC) -> bool:
"""
Detects circular references in branch structure
"""
visited = set()
rec_stack = set()
def dfs(acdc_said: str) -> bool:
if acdc_said in rec_stack:
return True # Cycle detected
if acdc_said in visited:
return False
visited.add(acdc_said)
rec_stack.add(acdc_said)
acdc = resolve_acdc(acdc_said)
for edge_said in acdc.edges:
if dfs(edge_said):
return True
rec_stack.remove(acdc_said)
return False
return dfs(root_acdc.said)
class BranchRecovery:
async def recover_broken_branch(self, branch_saids: List[str]) -> List[ACDC]:
recovered = []
for said in branch_saids:
try:
acdc = await self.resolve_with_retry(said, max_retries=3)
if self.validate_acdc(acdc):
recovered.append(acdc)
else:
# Attempt alternative resolution paths
acdc = await self.resolve_via_backup_witnesses(said)
if acdc:
recovered.append(acdc)
except Exception as e:
logger.warning(f"Failed to recover ACDC {said}: {e}")
# Continue with partial branch
return recovered
Branches must comply with ACDC specification requirements:
| ACDC Version | Branch Support | New Features |
|---|---|---|
| 1.0 | Basic edges | Simple DAG |
| 1.1 | Multi-parent | Diamond DAG |
| 1.2 | Conditional | Rule-based |
| 2.0 | Temporal | Time-based |
# Branch validation service deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: branch-validator
spec:
replicas: 3
template:
spec:
containers:
- name: validator
image: keri/branch-validator:v1.2
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
env:
- name: CACHE_SIZE
value: "10000"
- name: VALIDATION_TIMEOUT
value: "30s"
# Branch validation metrics
from prometheus_client import Counter, Histogram, Gauge
branch_validations = Counter('branch_validations_total', 'Total branch validations')
branch_validation_duration = Histogram('branch_validation_duration_seconds', 'Branch validation duration')
branch_cache_hits = Counter('branch_cache_hits_total', 'Branch cache hits')
branch_depth_gauge = Gauge('branch_max_depth', 'Maximum branch depth processed')
@branch_validation_duration.time()
def validate_branch_with_metrics(branch: List[ACDC]) -> bool:
branch_validations.inc()
branch_depth_gauge.set(len(branch))
result = validate_branch_logic(branch)
if result:
branch_cache_hits.inc()
return result
#!/bin/bash
# Branch health check script
BRANCH_ENDPOINT="https://api.example.com/branches"
ALERT_THRESHOLD=5000 # ms
for branch_id in $(cat critical_branches.txt); do
start_time=$(date +%s%3N)
response=$(curl -s -w "%{http_code}" "$BRANCH_ENDPOINT/$branch_id/validate")
http_code=${response: -3}
end_time=$(date +%s%3N)
duration=$((end_time - start_time))
if [ "$http_code" != "200" ] || [ "$duration" -gt "$ALERT_THRESHOLD" ]; then
echo "ALERT: Branch $branch_id validation failed or slow (${duration}ms)"
# Send alert to monitoring system
fi
done
class BranchMaintenance:
async def cleanup_expired_branches(self):
"""
Removes expired branches from cache and storage
"""
current_time = datetime.utcnow()
for branch_id, metadata in self.branch_registry.items():
if metadata.expires_at < current_time:
await self.remove_branch(branch_id)
logger.info(f"Cleaned up expired branch {branch_id}")
async def validate_branch_integrity_batch(self, batch_size: int = 100):
"""
Batch validation of stored branches for integrity
"""
branch_ids = list(self.branch_registry.keys())
for i in range(0, len(branch_ids), batch_size):
batch = branch_ids[i:i + batch_size]
tasks = [self.validate_branch_integrity(bid) for bid in batch]
results = await asyncio.gather(*tasks, return_exceptions=True)
for branch_id, result in zip(batch, results):
if isinstance(result, Exception):
logger.error(f"Branch {branch_id} integrity check failed: {result}")
await self.quarantine_branch(branch_id)