Attestation Class
Overview
The Attestation
class encapsulates a digital signature and additional metadata. Attestations are associated with verifiable data, credentials, and transactions and represent the main mechanism by which those data are verified.
The signature of an attestation authenticates the original data object’s serialized data, the serialization of all previous attestations in order, and the metadata of this attestation.
Package: keychain.core.attestation
from keychain.core.attestation import Attestation
Class Definition
class Attestation(SerializableObject):
"""An attestation is an encapsulation of a digital signature and additional metadata."""
Constructor
def __init__(
self,
serialized_string: Optional[bytes] = None,
serialization_format: SerializationFormat = SerializationFormat.PROTOBUF,
c_pointer: Optional[ctypes.c_void_p] = None,
) -> None
Initialize an Attestation object.
Parameters:
-
serialized_string
(bytes
, optional) - Serialized attestation bytes to deserialize -
serialization_format
(SerializationFormat
, optional) - Format of the serialized data (defaults to PROTOBUF) -
c_pointer
(ctypes.c_void_p
, optional) - Existing C pointer to wrap
Example:
from keychain.core.attestation import Attestation
from keychain.constants import SerializationFormat
# Create from serialized data
attestation_bytes = b"..." # Previously serialized attestation
attestation = Attestation(
serialized_string=attestation_bytes,
serialization_format=SerializationFormat.PROTOBUF
)
# Create from existing C pointer (typically from library functions)
attestation = Attestation(c_pointer=existing_pointer)
Class Methods
from_copy()
@classmethod
def from_copy(cls, other: "Attestation") -> "Attestation"
Create a copy of an attestation.
Parameters:
-
other
(Attestation
) - The attestation to copy
Returns: A new Attestation
instance that is a deep copy
Example:
original_attestation = get_attestation()
copied_attestation = Attestation.from_copy(original_attestation)
Instance Methods
copy()
def copy(self) -> "Attestation"
Create a deep copy of this attestation.
Returns: A new Attestation
instance that is a deep copy
serialize()
def serialize(self) -> bytes
Serialize the attestation.
Returns: Bytes serialization of the attestation in protobuf format
Example:
attestation = get_attestation()
serialized_data = attestation.serialize()
# Can be stored or transmitted and later reconstructed
restored_attestation = Attestation(serialized_data)
Properties
Core Signature Properties
index
@property
def index(self) -> int
Get the index (sequence number) of this attestation.
Returns: The index number of this attestation in the attestation chain
signature
@property
def signature(self) -> str
Get the digital signature.
Returns: The signature in hexadecimal format
Temporal Properties
timestamp
@property
def timestamp(self) -> int
Get the timestamp of when the attestation was created.
Returns: Timestamp as milliseconds since the epoch (Jan 1, 1970 00:00:00 UTC)
Example:
import datetime
attestation = get_attestation()
timestamp_ms = attestation.timestamp
timestamp_dt = datetime.datetime.fromtimestamp(timestamp_ms / 1000)
print(f"Attestation created at: {timestamp_dt}")
Approval and Status Properties
is_approval
@property
def is_approval(self) -> bool
Get whether the attestation signals approval or rejection.
Returns: True
if approval, False
if rejection
Example:
attestation = get_attestation()
if attestation.is_approval:
print("Attestation indicates approval")
else:
print("Attestation indicates rejection")
Metadata Properties
tags
@property
def tags(self) -> TagSet
Get the tags of the attestation.
Returns: The TagSet
used to store additional application-level data
Example:
attestation = get_attestation()
tags = attestation.tags
# Read application-specific metadata
app_id = tags.get_tag_value("app", "identifier")
priority = tags.get_tag_value("processing", "priority")
variables
@property
def variables(self) -> TagSet
Get the variables of the attestation.
Returns: The TagSet
to store mutable application-level stack variables
Example:
attestation = get_attestation()
variables = attestation.variables
# Read consensus state variables
consensus_stage = variables.get_tag_value("consensus", "stage")
participant_count = variables.get_tag_value("consensus", "participants")
Comparison Methods
eq()
def __eq__(self, other: object) -> bool
Compare attestations for equality.
Parameters:
-
other
(Attestation
) - The other attestation to compare
Returns: True
if attestations are equal, False
otherwise
Example:
attestation1 = get_attestation()
attestation2 = attestation1.copy()
if attestation1 == attestation2:
print("Attestations are identical")
Example: Working with Attestations
from keychain.core.attestation import Attestation
from keychain.constants import SignatureScheme
import datetime
def analyze_attestation(attestation: Attestation):
"""Analyze an attestation and display its properties."""
print("=== Attestation Analysis ===")
# Basic properties
print(f"Index: {attestation.index}")
print(f"Approval: {'Yes' if attestation.is_approval else 'No'}")
print(f"Reattachable: {'Yes' if attestation.is_reattachable else 'No'}")
# Cryptographic information
print(f"Algorithm: {attestation.algorithm.name}")
print(f"Public Key: {attestation.public_key[:32]}...") # First 32 chars
print(f"Signature: {attestation.signature[:32]}...") # First 32 chars
# Temporal information
timestamp_dt = datetime.datetime.fromtimestamp(attestation.timestamp / 1000)
print(f"Timestamp: {timestamp_dt}")
print(f"Version: {attestation.version.name}")
# Metadata
tags = attestation.tags
variables = attestation.variables
print(f"Tags available: {len(tags) > 0}")
print(f"Variables available: {len(variables) > 0}")
def verify_attestation_chain(attestations: list[Attestation]):
"""Verify that attestations form a valid chain."""
if not attestations:
return True
print("Verifying attestation chain...")
# Sort by index
sorted_attestations = sorted(attestations, key=lambda a: a.index)
for i, attestation in enumerate(sorted_attestations):
print(f"\\nAttestation {i}:")
print(f" Index: {attestation.index}")
print(f" Approval: {attestation.is_approval}")
if i > 0:
# Check that previous signature matches
prev_attestation = sorted_attestations[i-1]
if attestation.prev_signature == prev_attestation.signature:
print(" ✓ Chain link valid")
else:
print(" ✗ Chain link broken")
return False
else:
print(" ✓ First attestation in chain")
print("\\n✓ Attestation chain is valid")
return True
def create_attestation_summary(attestations: list[Attestation]) -> dict:
"""Create a summary of attestation properties."""
summary = {
"total_attestations": len(attestations),
"approval_count": 0,
"rejection_count": 0,
"algorithms_used": set(),
"reattachable_count": 0,
"timestamp_range": None
}
if not attestations:
return summary
timestamps = []
for attestation in attestations:
# Count approvals/rejections
if attestation.is_approval:
summary["approval_count"] += 1
else:
summary["rejection_count"] += 1
# Track algorithms
summary["algorithms_used"].add(attestation.algorithm.name)
# Count reattachable
if attestation.is_reattachable:
summary["reattachable_count"] += 1
# Collect timestamps
timestamps.append(attestation.timestamp)
# Calculate timestamp range
if timestamps:
min_ts = min(timestamps)
max_ts = max(timestamps)
min_dt = datetime.datetime.fromtimestamp(min_ts / 1000)
max_dt = datetime.datetime.fromtimestamp(max_ts / 1000)
summary["timestamp_range"] = (min_dt, max_dt)
# Convert set to list for JSON serialization
summary["algorithms_used"] = list(summary["algorithms_used"])
return summary
# Usage examples
def attestation_examples():
"""Demonstrate attestation usage."""
# Get attestations from some source (e.g., verifiable data)
attestations = get_attestations_from_credential()
if attestations:
# Analyze first attestation
analyze_attestation(attestations[0])
# Verify the chain
verify_attestation_chain(attestations)
# Create summary
summary = create_attestation_summary(attestations)
print(f"\\n=== Summary ===")
print(f"Total attestations: {summary['total_attestations']}")
print(f"Approvals: {summary['approval_count']}")
print(f"Rejections: {summary['rejection_count']}")
print(f"Algorithms: {', '.join(summary['algorithms_used'])}")
if summary['timestamp_range']:
start, end = summary['timestamp_range']
print(f"Time range: {start} to {end}")
if __name__ == "__main__":
attestation_examples()
Example: Attestation Metadata Usage
from keychain.core.attestation import Attestation
from keychain.core.tag_set import TagSet
def examine_attestation_metadata(attestation: Attestation):
"""Examine and work with attestation metadata."""
print("=== Attestation Metadata ===")
# Access tags (immutable application data)
tags = attestation.tags
print("Tags (application metadata):")
# Common tag namespaces
try:
# Application identification
app_name = tags.get_tag_value("app", "name")
app_version = tags.get_tag_value("app", "version")
print(f" Application: {app_name} v{app_version}")
except:
print(" No application metadata")
try:
# User/entity information
user_id = tags.get_tag_value("user", "id")
user_role = tags.get_tag_value("user", "role")
print(f" User: {user_id} (role: {user_role})")
except:
print(" No user metadata")
try:
# Context information
operation = tags.get_tag_value("context", "operation")
resource = tags.get_tag_value("context", "resource")
print(f" Context: {operation} on {resource}")
except:
print(" No context metadata")
# Access variables (mutable consensus state)
variables = attestation.variables
print("\\nVariables (consensus state):")
try:
# Consensus protocol state
stage = variables.get_tag_value("consensus", "stage")
participants = variables.get_tag_value("consensus", "participants")
print(f" Consensus: stage={stage}, participants={participants}")
except:
print(" No consensus state")
try:
# Transaction state
tx_status = variables.get_tag_value("transaction", "status")
tx_amount = variables.get_tag_value("transaction", "amount")
print(f" Transaction: status={tx_status}, amount={tx_amount}")
except:
print(" No transaction state")
def filter_attestations_by_criteria(attestations: list[Attestation]) -> dict:
"""Filter attestations by various criteria."""
filtered = {
"approvals": [],
"rejections": [],
"recent": [], # Last 24 hours
"high_security": [], # Strong algorithms
"reattachable": []
}
# Current time for recency check
current_time = datetime.datetime.now().timestamp() * 1000
day_ago = current_time - (24 * 60 * 60 * 1000)
# Strong signature algorithms
strong_algorithms = {
SignatureScheme.ECDSA_ECP_SECP384R1,
SignatureScheme.ECDSA_ECP_SECP521R1,
SignatureScheme.RSASS_PSS_4096
}
for attestation in attestations:
# Filter by approval status
if attestation.is_approval:
filtered["approvals"].append(attestation)
else:
filtered["rejections"].append(attestation)
# Filter by recency
if attestation.timestamp >= day_ago:
filtered["recent"].append(attestation)
# Filter by security level
if attestation.algorithm in strong_algorithms:
filtered["high_security"].append(attestation)
# Filter by reattachability
if attestation.is_reattachable:
filtered["reattachable"].append(attestation)
return filtered
def create_attestation_report(attestations: list[Attestation]) -> str:
"""Create a comprehensive report of attestations."""
report_lines = ["ATTESTATION ANALYSIS REPORT", "=" * 30, ""]
if not attestations:
report_lines.append("No attestations found.")
return "\\n".join(report_lines)
# Basic statistics
total = len(attestations)
approvals = sum(1 for a in attestations if a.is_approval)
rejections = total - approvals
reattachable = sum(1 for a in attestations if a.is_reattachable)
report_lines.extend([
f"Total Attestations: {total}",
f"Approvals: {approvals} ({approvals/total*100:.1f}%)",
f"Rejections: {rejections} ({rejections/total*100:.1f}%)",
f"Reattachable: {reattachable} ({reattachable/total*100:.1f}%)",
""
])
# Algorithm distribution
algorithm_counts = {}
for attestation in attestations:
alg_name = attestation.algorithm.name
algorithm_counts[alg_name] = algorithm_counts.get(alg_name, 0) + 1
report_lines.append("Algorithm Distribution:")
for algorithm, count in sorted(algorithm_counts.items()):
percentage = count / total * 100
report_lines.append(f" {algorithm}: {count} ({percentage:.1f}%)")
report_lines.append("")
# Timeline analysis
timestamps = [a.timestamp for a in attestations]
if timestamps:
min_ts = min(timestamps)
max_ts = max(timestamps)
min_dt = datetime.datetime.fromtimestamp(min_ts / 1000)
max_dt = datetime.datetime.fromtimestamp(max_ts / 1000)
duration = max_dt - min_dt
report_lines.extend([
"Timeline:",
f" First: {min_dt}",
f" Last: {max_dt}",
f" Duration: {duration}",
""
])
# Chain validation
sorted_attestations = sorted(attestations, key=lambda a: a.index)
chain_valid = True
broken_links = []
for i in range(1, len(sorted_attestations)):
current = sorted_attestations[i]
previous = sorted_attestations[i-1]
if current.prev_signature != previous.signature:
chain_valid = False
broken_links.append(i)
report_lines.extend([
f"Chain Validation: {'✓ Valid' if chain_valid else '✗ Invalid'}",
f"Broken Links: {len(broken_links)}"
])
if broken_links:
report_lines.append(f" Broken at indices: {broken_links}")
return "\\n".join(report_lines)
# Usage examples
def metadata_examples():
"""Demonstrate attestation metadata usage."""
attestations = get_attestations_from_transaction()
if attestations:
# Examine metadata of first attestation
examine_attestation_metadata(attestations[0])
# Filter attestations
filtered = filter_attestations_by_criteria(attestations)
print(f"\\nFiltered Results:")
print(f" Approvals: {len(filtered['approvals'])}")
print(f" Recent: {len(filtered['recent'])}")
print(f" High Security: {len(filtered['high_security'])}")
# Generate report
report = create_attestation_report(attestations)
print(f"\\n{report}")
if __name__ == "__main__":
metadata_examples()
Error Handling
Attestation operations can raise various exceptions:
Example:
from keychain.exceptions import KeychainValidationError, KeychainSecurityError
try:
# Create attestation from serialized data
attestation = Attestation(serialized_data)
# Access properties
signature = attestation.signature
public_key = attestation.public_key
timestamp = attestation.timestamp
# Check approval status
if attestation.is_approval:
print("Attestation indicates approval")
# Access metadata
tags = attestation.tags
variables = attestation.variables
except KeychainValidationError as e:
print(f"Validation error: {e}")
except KeychainSecurityError as e:
print(f"Security error: {e}")
except Exception as e:
print(f"Unexpected error: {e}")
See Also
-
TagSet Class - Used for attestation metadata
-
VerifiableData Class - Contains attestations
-
Credential Class - Uses attestations for verification
-
Transaction Class - Uses attestations for consensus
-
Constants and Enums - SignatureScheme and Version enums
-
Exception Classes - Error handling