Context Verification
Verify the authenticity and integrity of Quiet Stack contexts using blockchain records. Learn how to validate contexts, check signatures, and ensure data hasn't been tampered with.
How Verification Works
Quiet Stack uses cryptographic signatures and blockchain records for verification
What Gets Verified
- Authenticity: Context came from claimed agent
- Integrity: Data hasn't been modified
- Timestamp: Context created at claimed time
- Non-repudiation: Agent cannot deny creating it
Verification Levels
Full Verification
Signature + Blockchain + Hash validation
Signature Only
Cryptographic signature validation
Blockchain Only
Hash presence on blockchain
Basic Verification
Verify a context using its transaction hash or context ID
Python SDK
from quietstack import QuietStackClient
client = QuietStackClient(api_key="your_api_key")
# Method 1: Verify by transaction hash
verification = client.verify_context(
transaction_hash="0x1a2b3c4d5e6f7890abcdef..."
)
if verification.verified:
print("✅ Context verified successfully!")
print(f"Agent ID: {verification.agent_id}")
print(f"Block Number: {verification.block_number}")
print(f"Confirmations: {verification.confirmations}")
print(f"Verified at: {verification.block_timestamp}")
else:
print("❌ Verification failed")
print(f"Reason: {verification.error_reason}")
# Method 2: Verify by context ID
verification = client.verify_context(
context_id="ctx_1234567890abcdef"
)
# Method 3: Verify with local context data
context_data = {
"agent_id": "my-agent",
"timestamp": "2024-01-15T10:30:00Z",
"context_data": {"task": "classification", "result": "positive"},
"metadata": {"version": "1.0"}
}
verification = client.verify_context(
transaction_hash="0x1a2b3c4d5e6f7890...",
context=context_data # Compares local data with blockchain record
)JavaScript
// Using fetch API directly
const client = { apiKey: 'your_api_key' };
// Method 1: Verify by transaction hash
try {
const verification = await client.verify({
transaction_hash: '0x1a2b3c4d5e6f7890abcdef...'
});
if (verification.verified) {
console.log('✅ Context verified successfully!');
console.log(`Agent ID: ${verification.agent_id}`);
console.log(`Block Number: ${verification.block_number}`);
console.log(`Confirmations: ${verification.confirmations}`);
} else {
console.log('❌ Verification failed');
}
} catch (error) {
console.error('Verification error:', error.message);
}
// Method 2: Verify with context validation
const verification = await client.verify({
transaction_hash: '0x1a2b3c4d5e6f7890...',
context: {
agent_id: 'my-agent',
timestamp: '2024-01-15T10:30:00Z',
context_data: { task: 'classification', result: 'positive' },
metadata: { version: '1.0' }
}
});
// Check specific verification aspects
console.log(`Signature valid: ${verification.signature_valid}`);
console.log(`Hash matches: ${verification.hash_matches}`);
console.log(`On blockchain: ${verification.block_number > 0}`);Batch Verification
Verify multiple contexts efficiently in a single request
Python Implementation
# Verify multiple contexts at once
transaction_hashes = [
"0x1a2b3c4d5e6f7890...",
"0x9876543210fedcba...",
"0xabcdef1234567890..."
]
# Batch verify (more efficient than individual calls)
verifications = client.verify_contexts_batch(transaction_hashes)
# Process results
for i, verification in enumerate(verifications):
tx_hash = transaction_hashes[i]
if verification.verified:
print(f"✅ {tx_hash[:10]}... verified (Block: {verification.block_number})")
else:
print(f"❌ {tx_hash[:10]}... failed ({verification.error_reason})")
# Summary statistics
total = len(verifications)
verified = sum(1 for v in verifications if v.verified)
print(f"\nVerification Summary: {verified}/{total} contexts verified ({verified/total*100:.1f}%)")
# Filter for different verification statuses
confirmed = [v for v in verifications if v.verified and v.confirmations >= 12]
pending = [v for v in verifications if v.verified and v.confirmations < 12]
failed = [v for v in verifications if not v.verified]
print(f"Confirmed: {len(confirmed)}, Pending: {len(pending)}, Failed: {len(failed)}")JavaScript Implementation
// Verify multiple contexts concurrently
const transactionHashes = [
'0x1a2b3c4d5e6f7890...',
'0x9876543210fedcba...',
'0xabcdef1234567890...'
];
// Method 1: Batch API call (recommended)
const verifications = await client.verifyBatch(transactionHashes);
// Process results
verifications.forEach((verification, index) => {
const txHash = transactionHashes[index];
if (verification.verified) {
console.log(`✅ ${txHash.substring(0, 10)}... verified (Block: ${verification.block_number})`);
} else {
console.log(`❌ ${txHash.substring(0, 10)}... failed (${verification.error_reason})`);
}
});
// Method 2: Concurrent individual calls
const verifyPromises = transactionHashes.map(hash =>
client.verify({ transaction_hash: hash })
);
const results = await Promise.allSettled(verifyPromises);
// Handle mixed success/failure
results.forEach((result, index) => {
const txHash = transactionHashes[index];
if (result.status === 'fulfilled' && result.value.verified) {
console.log(`✅ ${txHash.substring(0, 10)}... verified`);
} else {
const reason = result.status === 'rejected'
? result.reason.message
: result.value.error_reason;
console.log(`❌ ${txHash.substring(0, 10)}... failed: ${reason}`);
}
});Verification Response Format
Understanding the verification response structure
Successful Verification
{
"verified": true,
"transaction_hash": "0x1a2b3c4d5e6f7890abcdef123456789012345678",
"block_number": 123456789,
"block_timestamp": "2024-01-15T10:30:05Z",
"confirmations": 15,
"agent_id": "my-classification-agent",
"context_hash": "0xabcdef1234567890fedcba0987654321abcdef12",
"signature_valid": true,
"hash_matches": true,
"verification_time": "2024-01-15T11:45:23Z",
"network": "polygon",
"gas_used": 42000,
"verification_details": {
"signature_algorithm": "ECDSA",
"hash_algorithm": "SHA-256",
"public_key": "0x04a1b2c3d4e5f6...",
"signature": "0x789abc..."
}
}Failed Verification
{
"verified": false,
"transaction_hash": "0x1a2b3c4d5e6f7890abcdef123456789012345678",
"error_reason": "SIGNATURE_INVALID",
"error_details": "Digital signature does not match expected value",
"context_hash": "0xabcdef1234567890fedcba0987654321abcdef12",
"signature_valid": false,
"hash_matches": true, // Hash found on blockchain but signature invalid
"verification_time": "2024-01-15T11:45:23Z",
"network": "polygon",
"block_number": 123456789, // May still be present if found
"possible_causes": [
"Context data was modified after signing",
"Incorrect agent private key used for signing",
"Corrupted signature during transmission"
]
}Verification Status and Timing
Understanding confirmation times and blockchain finality
Confirmation Timeline
0-1 min
Transaction Pending
Submitted to mempool, waiting for inclusion
1-5 min
First Confirmation
Included in a block, basic verification possible
5-15 min
Confirmed
12+ confirmations, considered final on most networks
Network Comparison
| Network | Block Time | Safe Confirmations | Finality Time |
|---|---|---|---|
| Polygon | ~2 seconds | 12 blocks | ~30 seconds |
| Ethereum | ~12 seconds | 12 blocks | ~2.4 minutes |
| Arbitrum | ~1 second | 20 blocks | ~20 seconds |
| Base | ~2 seconds | 12 blocks | ~30 seconds |
Checking Confirmation Status
# Poll for confirmation status
import time
def wait_for_confirmation(client, transaction_hash, required_confirmations=12, timeout=300):
start_time = time.time()
while time.time() - start_time < timeout:
verification = client.verify_context(transaction_hash)
if not verification.verified:
print(f"❌ Verification failed: {verification.error_reason}")
return False
confirmations = verification.confirmations
print(f"Confirmations: {confirmations}/{required_confirmations}")
if confirmations >= required_confirmations:
print(f"✅ Context confirmed with {confirmations} confirmations")
return True
time.sleep(10) # Check every 10 seconds
print(f"⏰ Timeout waiting for confirmations")
return False
# Usage
result = client.contexts.create(context)
confirmed = wait_for_confirmation(client, result.transaction_hash)
if confirmed:
print("Ready to use verified context")
else:
print("Context not yet confirmed, but may still be valid")Manual Verification
Verify contexts manually using blockchain explorers and cryptographic tools
Using Blockchain Explorers
Step 1: Look up Transaction
Use the transaction hash to find the transaction on a blockchain explorer
Step 2: Find Contract Event
Look for the ContextLogged event in the transaction logs
Event: ContextLogged(bytes32 indexed contextHash, string agentId, uint256 timestamp)Step 3: Verify Hash
Compare the contextHash in the event with the hash of your context data
Cryptographic Verification
# Manual cryptographic verification
import hashlib
import json
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import ec
def verify_context_signature(context, signature, public_key_pem):
"""
Manually verify a Quiet Stack context signature
"""
# 1. Serialize context (excluding signature and hash fields)
context_for_signing = {
"agent_id": context["agent_id"],
"timestamp": context["timestamp"],
"context_data": context["context_data"],
"metadata": context.get("metadata", {})
}
# 2. Create canonical JSON representation
context_json = json.dumps(context_for_signing, sort_keys=True, separators=(',', ':'))
# 3. Hash the context
context_bytes = context_json.encode('utf-8')
context_hash = hashlib.sha256(context_bytes).digest()
# 4. Load public key
public_key = serialization.load_pem_public_key(public_key_pem.encode())
# 5. Verify signature
try:
public_key.verify(
bytes.fromhex(signature),
context_hash,
ec.ECDSA(hashes.SHA256())
)
return True, context_hash.hex()
except Exception as e:
return False, str(e)
# Example usage
context = {
"agent_id": "my-agent",
"timestamp": "2024-01-15T10:30:00Z",
"context_data": {"task": "test"},
"signature": "3045022100..."
}
public_key_pem = """-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----"""
is_valid, result = verify_context_signature(context, context["signature"], public_key_pem)
print(f"Signature valid: {is_valid}")
print(f"Context hash: {result}")Verification Best Practices
Guidelines for effective context verification
✅ Best Practices
- Always verify contexts before trusting them
- Check both signature and blockchain confirmation
- Use batch verification for multiple contexts
- Implement retry logic for pending transactions
- Cache verification results to avoid redundant checks
- Set appropriate confirmation requirements for your use case
⚠️ Common Pitfalls
- Accepting contexts without verification
- Not handling verification failures gracefully
- Assuming immediate blockchain finality
- Ignoring network-specific confirmation requirements
- Not validating context structure before verification
- Relying solely on client-side verification
Verification Tools & Resources
CLI Commands
quietstack verify <tx_hash>quietstack verify-batch <file.txt>quietstack verify-context <context.json>