This document provides practical examples of using the Hybrid Verification Framework with different protocols and workflows.
- Quick Start: Raft Protocol
- Adding a New Protocol
- Hybrid Verification Workflow
- Property Synthesis Workflow
- Code Generation Workflow
- Protocol-Agnostic Usage
# Generate properties
python tools/generate_properties.py raft
# Generate KLEE test harness
python tools/generate_klee_test.py raft
# Generate TLA+ specification
python tools/generate_tla_spec.py raftcd examples/raft/test_harness
make run-klee
# Or using Docker:
./run_docker.batcd examples/raft/test_harness
python extract_klee_counterexamples.py klee-out-0 > counterexamples.json# Windows
cd verification
.\refinement_loop.bat raft
# Linux/Mac
bash verification/refinement_loop.sh raftCreate examples/my_protocol/config/my_protocol.yaml:
protocol:
name: "MyProtocol"
domain: "consensus"
adapter: "examples/my_protocol/adapter/my_protocol_adapter.c"
adapter_factory: "create_my_protocol_definition"
description: "A simple consensus protocol"
configuration:
num_nodes: 3
max_rounds: 10
timeout_range: [100, 200]
properties:
- name: "LeaderUniqueness"
type: "safety"
template: "uniqueness.yaml"
variables:
ENTITY: "Leader"
CONTEXT: "round"
ENTITY_FIELD: "role"
CONTEXT_FIELD: "current_round"
MAX_CONTEXT: 10
description: "At most one leader per round"
- name: "Agreement"
type: "safety"
template: "agreement.yaml"
variables:
VALUE: "decision"
FIELD: "decided_value"
CONDITION: "nodes[i].decided == true"
description: "All nodes agree on the decided value"
state_variables:
- name: "id"
type: "int"
description: "Node identifier"
- name: "role"
type: "Role"
description: "Current role (LEADER, FOLLOWER)"
- name: "current_round"
type: "int"
description: "Current round number"
- name: "decided_value"
type: "int"
description: "Decided value (if decided)"
- name: "decided"
type: "bool"
description: "Whether node has decided"
message_types:
- name: "PROPOSE"
description: "Propose a value"
- name: "ACCEPT"
description: "Accept a proposal"Create examples/my_protocol/adapter/my_protocol_adapter.c:
#include "core/system_interface.h"
#include "my_protocol_adapter.h"
// Node structure
typedef struct {
int id;
Role role;
int current_round;
int decided_value;
bool decided;
} MyProtocolNode;
// Message structure
typedef struct {
int sender_id;
int round;
int value;
MessageType type;
} MyProtocolMessage;
// Initialize node
static void my_protocol_init_node(SystemNode* node, int id, SystemConfig* config) {
MyProtocolNode* n = (MyProtocolNode*)node;
n->id = id;
n->role = FOLLOWER;
n->current_round = 0;
n->decided = false;
}
// Process message
static void my_protocol_process_message(SystemNode* node, SystemMessage* msg,
void* network_state, void* metrics) {
MyProtocolNode* n = SYSTEM_NODE(node, MyProtocolNode);
MyProtocolMessage* m = SYSTEM_MSG(msg, MyProtocolMessage);
// Process message based on type
if (m->type == PROPOSE && n->role == FOLLOWER) {
n->decided_value = m->value;
n->decided = true;
}
// ... more message processing
}
// Generate message
static SystemMessage* my_protocol_generate_message(SystemNode* node, int target_id) {
MyProtocolNode* n = SYSTEM_NODE(node, MyProtocolNode);
if (n->role == LEADER) {
MyProtocolMessage* msg = malloc(sizeof(MyProtocolMessage));
msg->sender_id = n->id;
msg->round = n->current_round;
msg->type = PROPOSE;
msg->value = n->decided_value;
return (SystemMessage*)msg;
}
return NULL;
}
// Verify safety
static int my_protocol_verify_safety(SystemNode* nodes[], int num_nodes, void* metrics) {
// Check leader uniqueness
int leaders = 0;
for (int i = 0; i < num_nodes; i++) {
MyProtocolNode* n = SYSTEM_NODE(nodes[i], MyProtocolNode);
if (n->role == LEADER) {
leaders++;
}
}
if (leaders > 1) {
return 0; // Safety violation
}
// Check agreement
int decided_value = -1;
for (int i = 0; i < num_nodes; i++) {
MyProtocolNode* n = SYSTEM_NODE(nodes[i], MyProtocolNode);
if (n->decided) {
if (decided_value == -1) {
decided_value = n->decided_value;
} else if (decided_value != n->decided_value) {
return 0; // Agreement violation
}
}
}
return 1; // Safety properties hold
}
// Verify liveness
static int my_protocol_verify_liveness(SystemNode* nodes[], int num_nodes,
int round, void* metrics) {
// Check if a leader is elected
for (int i = 0; i < num_nodes; i++) {
MyProtocolNode* n = SYSTEM_NODE(nodes[i], MyProtocolNode);
if (n->role == LEADER) {
return 1; // Leader exists
}
}
// If no leader after many rounds, liveness violation
if (round > 10) {
return 0;
}
return 1;
}
// Allocate nodes
static void my_protocol_alloc_nodes(SystemNode** nodes, int num_nodes) {
*nodes = malloc(sizeof(MyProtocolNode) * num_nodes);
}
// Free nodes
static void my_protocol_free_nodes(SystemNode* nodes, int num_nodes) {
free(nodes);
}
// Free message
static void my_protocol_free_message(SystemMessage* msg) {
free(msg);
}
// Operations structure
static SystemOperations my_protocol_ops = {
.initialize_node = my_protocol_init_node,
.process_message = my_protocol_process_message,
.generate_message = my_protocol_generate_message,
.should_send_message = NULL, // Optional
.verify_safety = my_protocol_verify_safety,
.verify_liveness = my_protocol_verify_liveness,
.verify_invariant = NULL, // Optional
.alloc_nodes = my_protocol_alloc_nodes,
.free_nodes = my_protocol_free_nodes,
.free_message = my_protocol_free_message
};
// Default configuration
static SystemConfig my_protocol_default_config = {
.num_nodes = 3,
.max_rounds = 10,
.timeout_range = {100, 200},
.domain_specific = NULL
};
// Factory function
SystemDefinition* create_my_protocol_definition(void) {
SystemDefinition* def = malloc(sizeof(SystemDefinition));
def->name = "MyProtocol";
def->domain = "consensus";
def->ops = &my_protocol_ops;
def->default_config = &my_protocol_default_config;
def->property_definitions = NULL;
return def;
}# Generate properties
python tools/generate_properties.py my_protocol
# Generate KLEE harness
python tools/generate_klee_test.py my_protocol
# Generate TLA+ spec
python tools/generate_tla_spec.py my_protocol# Run hybrid verification
bash verification/refinement_loop.sh my_protocol# 1. Generate verification code
python tools/generate_properties.py raft
python tools/generate_klee_test.py raft
python tools/generate_tla_spec.py raft
# 2. Run KLEE
cd examples/raft/test_harness
make run-klee
# 3. Extract KLEE counterexamples
python extract_klee_counterexamples.py klee-out-0 > klee_counterexamples.json
# 4. Convert KLEE to TLA+
cd ../..
python verification/counterexample_converter.py \
--klee-to-tla examples/raft/test_harness/klee_counterexamples.json \
--output-dir verification/iterations/iteration_1 \
--protocol raft
# 5. Run TLA+ model checking (in TLA+ Toolbox)
# Open examples/raft/spec/Raft.tla and run model checking
# 6. Extract TLA+ counterexamples
python examples/raft/spec/extract_tla_counterexamples.py examples/raft/spec > examples/raft/spec/tla_counterexamples.json
# 7. Convert TLA+ to KLEE
python verification/counterexample_converter.py \
--tla-to-klee examples/raft/spec/tla_counterexamples.json \
--output-dir verification/iterations/iteration_1 \
--protocol raft
# 8. Create guided initialization
python verification/create_tla_guided_json.py \
examples/raft/spec/tla_counterexamples.json \
--protocol raft
# 9. Run refinement loop (automates steps 2-8)
bash verification/refinement_loop.sh raft# Analyze counterexamples (generic mode)
python synthesis/analyze_counterexample.py \
examples/raft/test_harness/klee-out-0/counterexamples.json
# Analyze with protocol-specific patterns
python synthesis/analyze_counterexample.py \
examples/raft/test_harness/klee-out-0/counterexamples.json \
--protocol raft# Synthesize properties from analysis
python synthesis/synthesize_property.py \
counterexample_analysis.json
# Refine properties
python synthesis/property_refinement.py \
counterexample_analysis.json#!/usr/bin/env python3
from synthesis.analyze_counterexample import analyze_counterexample
from synthesis.synthesize_property import synthesize_property
# Analyze counterexamples
analysis = analyze_counterexample('counterexamples.json', 'raft')
# Synthesize new properties
synthesized = synthesize_property(analysis)
# Save synthesized properties
import json
with open('synthesized_properties.json', 'w') as f:
json.dump(synthesized, f, indent=2)#!/usr/bin/env python3
from tools.generate_properties import PropertyGenerator
from tools.generate_klee_test import KLEETestGenerator
from tools.generate_tla_spec import TLASpecGenerator
protocol = 'raft'
# Generate properties
prop_gen = PropertyGenerator()
prop_result = prop_gen.generate_properties(protocol)
print(f"Properties generated: {prop_result['json']}")
# Generate KLEE harness
klee_gen = KLEETestGenerator()
klee_file = klee_gen.generate_harness(protocol)
print(f"KLEE harness generated: {klee_file}")
# Generate TLA+ spec
tla_gen = TLASpecGenerator()
tla_file = tla_gen.generate_spec(protocol)
print(f"TLA+ spec generated: {tla_file}")from tools.template_loader import TemplateLoader
loader = TemplateLoader()
# Load property template
template = loader.load_property_template('uniqueness')
# Customize variables
variables = {
'ENTITY': 'Coordinator',
'CONTEXT': 'epoch',
'ENTITY_FIELD': 'role',
'CONTEXT_FIELD': 'current_epoch',
'MAX_CONTEXT': '20'
}
# Expand template
result = loader.expand_property_template('uniqueness', variables)
print("KLEE Code:")
print(result['klee_code'])
print("\nTLA+ Code:")
print(result['tla_code'])from verification.counterexample_converter import (
convert_klee_to_tla,
convert_tla_to_klee
)
# Generic KLEE counterexample
klee_cex = {
'counterexample_id': 'generic_001',
'property': 'SafetyProperty',
'assertion': 'klee_assert(condition)',
'symbolic_values': {
'var1': 10,
'var2': [1, 2, 3, 4, 5]
}
}
# Convert to TLA+ (no protocol specified)
tla_result = convert_klee_to_tla(klee_cex)
print(tla_result['tla_code'])
# Generic TLA+ counterexample
tla_cex = {
'counterexample_id': 'generic_002',
'property': 'Invariant',
'violated_invariant': 'TypeOK',
'state': {
'var1': 10,
'var2': [1, 2, 3, 4, 5]
}
}
# Convert to KLEE (no protocol specified)
klee_result = convert_tla_to_klee(tla_cex)
print(klee_result['klee_code'])from synthesis.analyze_counterexample import identify_property_violation
# Generic counterexample
cex = {
'assertion': 'klee_assert(entities <= 1)',
'message': 'Uniqueness property violated: multiple entities per context',
'property': 'UniquenessViolation'
}
# Identify violation (no protocol specified)
violation = identify_property_violation(cex)
print(f"Violation Type: {violation['violation_type']}")
print(f"Pattern: {violation['pattern']}")
print(f"Description: {violation['description']}")Create templates/domains/my_domain_system.yaml:
domain: "my_domain"
description: "Custom domain template"
components:
- name: "Node"
type: "entity"
- name: "Message"
type: "communication"
operations:
- name: "initialize"
description: "Initialize component"
- name: "process"
description: "Process event"Create templates/properties/custom_property.yaml:
name: "custom_property"
type: "safety"
description: "Custom property template"
klee_template: |
// Check {PROPERTY_NAME}
int {VARIABLE_NAME} = 0;
for (int i = 0; i < NUM_NODES; i++) {
if ({CONDITION}) {
{VARIABLE_NAME}++;
}
}
klee_assert({VARIABLE_NAME} {OPERATOR} {THRESHOLD});
tla_template: |
{PROPERTY_NAME} ==
\\A i, j \\in 1..NumNodes :
{CONDITION} => {VALUE_EXPRESSION}-
Protocol not found:
- Ensure
examples/{protocol}/config/{protocol}.yamlexists - Check protocol name spelling
- Ensure
-
Template not found:
- Ensure template file exists in
templates/domains/ortemplates/properties/ - Check template name spelling
- Ensure template file exists in
-
Adapter not found:
- Ensure adapter file exists at
examples/{protocol}/adapter/{protocol}_adapter.c - Check factory function name matches config
- Ensure adapter file exists at
-
Code generation fails:
- Verify protocol configuration is valid YAML
- Check that all required fields are present
- API Documentation - Complete API reference
- Testing Guide - How to run tests