A production-ready decentralized identity and credential management system built on the Sui blockchain, designed specifically for IoT devices and robotics applications with full W3C DID Core specification compliance.
Suibotics DID provides a comprehensive framework for managing digital identities and verifiable credentials in IoT ecosystems. The system enables secure device authentication, credential issuance, and trust establishment between IoT devices, certificate authorities, and service providers. Built with type safety, comprehensive validation, production-grade error handling, and advanced batch operations for efficient fleet management.
- DID Registration: Create unique decentralized identifiers for IoT devices
- Key Management: Add, revoke, and manage cryptographic keys with type-safe dynamic field handling
- Service Endpoints: Complete service lifecycle management (add, update, remove)
- Controller Verification: Ensure only authorized entities can modify DID documents
- W3C DID Document Resolution: Full compliance with W3C DID Core specification
- Type-Safe Architecture: Prevents key/service ID collisions with wrapper structs
- Bulk DID Registration: Register up to 50 DIDs in a single transaction for device fleet onboarding
- Batch Key Management: Add or revoke keys across multiple DIDs simultaneously
- Batch Service Operations: Bulk add, update, or remove service endpoints across device fleets
- Batch Credential Operations: Issue or revoke credentials in bulk for fleet-wide operations
- Partial Success Handling: Individual operation failures don't affect successful operations
- Gas Optimization: Significant cost savings for fleet management operations
- Detailed Result Tracking: Complete success/failure reporting for each operation
- Credential Issuance: Issue tamper-proof credentials to devices
- Schema Validation: Support for structured credential schemas
- Revocation Management: Revoke credentials when necessary
- Timestamp Tracking: Track credential issuance and revocation times
- Credential Discovery: Multi-dimensional indexing for efficient credential lookup
- Input Validation: Comprehensive validation for all inputs
- Access Control: Role-based access control for DID and credential operations
- Event Logging: Immutable event logs for all operations with comprehensive change tracking
- Error Handling: Robust error handling with descriptive error codes
- Type Safety: Dynamic field type confusion prevention with KeyFieldKey/ServiceFieldKey wrappers
- DID Documents: Full W3C DID Core specification compliance
- Verification Methods: Support for multiple key types and purposes
- Service Endpoints: Standards-compliant service registration and management
- Resolution: Complete DID document resolution from on-chain data
The system consists of three focused modules with clean separation of concerns:
- identity_types (
sources/identity_types.move): Core data structures, validation logic, and W3C DID document building - did_registry (
sources/did_registry.move): DID registration, key management, service lifecycle, and batch operations - credential_registry (
sources/credential_registry.move): Credential issuance, revocation, discovery, and batch operations
- Type-Safe Dynamic Fields: Separate namespaces for keys and services prevent ID collisions
- DID Document Resolution: On-chain data structures that build W3C-compliant DID documents
- Service Lifecycle Management: Complete add → update → remove workflow with audit trails
- Batch Processing: Efficient bulk operations with partial success handling
- Production-Ready Patterns: Comprehensive error handling, validation, and event emission
Suibotics DID uses two separate registry systems that serve distinct but complementary purposes:
Purpose: Manages Decentralized Identifiers (DIDs) and their associated identity data
What it stores:
- DID documents with verification methods (public keys)
- Service endpoints (like MQTT brokers, API endpoints)
- Name-to-address mappings for human-readable DID names
- Key management (add, revoke keys)
Key functions:
// Register a new DID identity
did_registry::register_did(registry, name, pubkey, purpose, ctx)
// Add keys for different purposes (authentication, assertion, etc.)
did_registry::add_key(did, key_id, pubkey, purpose, ctx)
// Manage service endpoints
did_registry::add_service(did, service_id, service_type, endpoint, ctx)
did_registry::update_service(did, service_id, new_type, new_endpoint, ctx)
did_registry::remove_service(did, service_id, ctx)
// Build W3C-compliant DID documents
did_registry::build_did_document(did, did_string, key_ids, service_ids)
// ✨ NEW: Batch operations for fleet management
did_registry::register_dids_batch(registry, names, pubkeys, purposes, ctx)
did_registry::add_keys_batch(dids, key_ids, pubkeys, purposes, ctx)
did_registry::revoke_keys_batch(dids, key_ids, ctx)
did_registry::add_services_batch(dids, service_ids, types, endpoints, ctx)
did_registry::update_services_batch(dids, service_ids, new_types, new_endpoints, ctx)
// ⭐ NEW: Reverse lookup capabilities for registry queries
did_registry::get_did_controller_by_name(registry, name)
did_registry::get_dids_by_controller(registry, controller)
did_registry::get_dids_by_service_type(registry, service_type)
did_registry::get_dids_by_key_purpose(registry, purpose)
did_registry::get_dids_by_time_range(registry, start_time, end_time)
did_registry::get_registry_stats(registry)
did_registry::did_name_exists(registry, name)Purpose: Manages Verifiable Credentials and enables credential discovery
What it stores:
- Credential metadata (issuer, subject, schema, timestamps)
- Discovery indices (by subject, issuer, schema, time ranges)
- Revocation status tracking
- Registry statistics (total credentials, active, revoked)
Key functions:
// Issue credentials to subjects
credential_registry::issue_credential(registry, subject, schema, data_hash, ctx)
// Revoke credentials
credential_registry::revoke_credential(registry, credential, ctx)
// Discovery functions
credential_registry::get_credentials_by_subject(registry, subject)
credential_registry::get_credentials_by_issuer(registry, issuer)
credential_registry::get_credentials_by_schema(registry, schema)
credential_registry::get_active_credentials_by_subject(registry, subject)
// ✨ NEW: Batch operations for fleet management
credential_registry::issue_credentials_batch(registry, subjects, issuers, schemas, hashes, ctx)
credential_registry::revoke_credentials_batch(credentials, ctx)Both registries support efficient batch processing with the following design principles:
public struct BatchResult has copy, drop {
index: u64, // Operation index in the batch
success: bool, // Whether this operation succeeded
error_code: u64, // Error code if operation failed
}- ✅ Individual failures don't affect successful operations
- ✅ Detailed tracking of which operations succeeded/failed
- ✅ Granular error codes for debugging
- ✅ Size limits (max 50 operations) prevent gas issues
// Count successful operations
count_batch_successes(results: &vector<BatchResult>): u64
// Get indices of failed operations
get_batch_failures(results: &vector<BatchResult>): vector<u64>
// Check if entire batch succeeded
is_batch_fully_successful(results: &vector<BatchResult>): bool| Aspect | DID Registry | Credential Registry |
|---|---|---|
| Data Focus | Identity & verification methods | Attestations & claims |
| Ownership | DIDs owned by controllers | Credentials owned by subjects |
| Discovery | Name-based lookup | Multi-dimensional indexing |
| Lifecycle | Create → Update → (Keys/Services) | Issue → Verify → Revoke |
| Batch Ops | Device fleet onboarding | Bulk credential management |
| Standards | W3C DID Core specification | W3C VC Data Model |
- Separation of Concerns: Identity management vs. credential management are distinct functions
- Scalability: Each registry can be optimized for its specific access patterns
- Security: Different access controls and validation rules
- Standards Compliance: Each follows different W3C specifications
// 1. Alice registers her DID (identity)
did_registry::register_did(&mut did_registry, b"alice_ca", pubkey, b"authentication", ctx);
// 2. Alice issues a credential to Bob (using her DID as issuer)
credential_registry::issue_credential(&mut cred_registry, BOB, b"DeviceCert", hash, ctx);
// 3. Bob can discover all credentials issued to him
let bobs_creds = credential_registry::get_credentials_by_subject(&cred_registry, BOB);
// 4. Anyone can resolve Alice's DID to verify her keys
let alice_did_doc = did_registry::build_did_document(&alice_did, did_string, key_ids, service_ids);
// ✨ 5. NEW: Bulk operations for fleet management
// Register 25 IoT devices in one transaction
let results = did_registry::register_dids_batch(&mut registry, device_names, pubkeys, purposes, ctx);
// Issue firmware attestations to the fleet
let cred_results = credential_registry::issue_credentials_batch(
&mut cred_registry, devices, issuers, schemas, hashes, ctx
);This separation makes the system more modular, secure, and allows each registry to be optimized for its specific use case, while batch operations enable efficient fleet management.
- Sui CLI: Version 1.49.1 or later
- Move Language: Compatible with Sui Move framework
# macOS (using Homebrew)
brew install sui
# Or update existing installation
brew update && brew upgrade sui
# Verify installation
sui --version-
Clone the repository:
git clone <repository-url> cd suibotics_did
-
Build the project:
sui move build
-
Run tests:
sui move test
The project includes comprehensive test suites covering all major functionality with extensive edge case testing:
tests/did_registry_tests.move: 17 tests covering DID registration, key management, service lifecycle, and W3C compliancetests/simple_test.move: 6 integration tests covering basic workflowstests/suibotics_core_tests.move: 2 end-to-end scenario teststests/batch_operations_tests.move: 6 tests covering all batch operations functionality ✨ NEWtests/reverse_lookup_tests.move: 6 tests covering all reverse lookup functionality ⭐ NEW
# Run all tests
sui move test
# Run specific test module
sui move test did_registry_tests
# Run batch operations tests
sui move test batch_operations_tests
# Run with verbose output
sui move test --verbose✅ 33/33 tests passing - 100% test success rate
Test Categories:
- DID Registration and Management
- Key Addition and Revocation
- Service Endpoint Lifecycle Management (add/update/remove)
- W3C DID Document Resolution
- Type-Safe Dynamic Field Handling
- Credential Issuance and Revocation
- ✨ Batch Operations (DID and Credential) - 6 comprehensive tests
- ✨ Partial Success Handling - Edge cases and validation
- ✨ Batch Result Utilities - Success/failure tracking
- ✨ Essential Reverse Lookup - 3 practical tests ⭐ SIMPLIFIED
- Access Control and Security
- Input Validation and Error Handling
- Edge Cases and Collision Prevention
// Initialize the DID registry
did_registry::test_init(ctx);
// Register a new DID
did_registry::register_did(
&mut registry,
b"device_001", // DID name
device_public_key, // Device's public key
b"authentication", // Key purpose
ctx
);// Add a new key for signing operations
did_registry::add_key(
&mut did_info,
b"signing_key", // Key identifier
signing_public_key, // Public key
b"assertion", // Key purpose
ctx
);
// Revoke a key
did_registry::revoke_key(
&mut did_info,
b"signing_key", // Key identifier to revoke
ctx
);// Add an MQTT service endpoint
did_registry::add_service(
&mut did_info,
b"mqtt_broker", // Service ID
b"MQTTBroker", // Service type
b"mqtt://device.local:1883", // Endpoint URL
ctx
);
// Update the service endpoint
did_registry::update_service(
&mut did_info,
b"mqtt_broker", // Service ID
b"MQTTBroker", // New service type
b"mqtt://device.local:8883", // New endpoint URL
ctx
);
// Remove the service
did_registry::remove_service(
&mut did_info,
b"mqtt_broker", // Service ID to remove
ctx
);// Build a complete W3C-compliant DID document
let did_document = did_registry::build_did_document(
&did_info,
verification_methods, // Custom verification methods
services, // Custom services
);
// Or build with basic configuration
let basic_document = did_registry::build_basic_did_document(&did_info);// Issue a firmware attestation credential
credential_registry::issue_credential(
device_address, // Credential subject
b"FirmwareAttestation", // Credential schema
firmware_hash, // Data hash
ctx
);// Register 25 IoT devices in a single transaction
let device_names = vector[b"sensor_001", b"sensor_002", /*...*/];
let device_pubkeys = vector[pubkey1, pubkey2, /*...*/];
let purposes = vector[b"auth", b"auth", /*...*/];
let results = did_registry::register_dids_batch(
&mut registry,
device_names,
device_pubkeys,
purposes,
ctx
);
// Check results
let success_count = did_registry::count_batch_successes(&results);
let failures = did_registry::get_batch_failures(&results);
assert!(success_count == 25, 1); // All devices registered successfully// Issue firmware attestation credentials to device fleet
let subjects = vector[device1_addr, device2_addr, device3_addr];
let issuers = vector[ca_addr, ca_addr, ca_addr];
let schemas = vector[b"FirmwareAttest", b"FirmwareAttest", b"FirmwareAttest"];
let hashes = vector[fw_hash1, fw_hash2, fw_hash3];
let results = credential_registry::issue_credentials_batch(
&mut cred_registry,
subjects,
issuers,
schemas,
hashes,
ctx
);
// Verify all credentials issued successfully
assert!(credential_registry::is_batch_fully_successful(&results), 1);// Revoke compromised keys across multiple devices
let compromised_key_ids = vector[b"backup_key", b"backup_key", b"backup_key"];
let results = did_registry::revoke_keys_batch(
&mut device_dids,
compromised_key_ids,
ctx
);
// Track which devices had keys successfully revoked
let revoked_count = did_registry::count_batch_successes(&results);// Batch operation with mixed results
let results = did_registry::register_dids_batch(
&mut registry,
names_with_duplicate, // One name already exists
pubkeys,
purposes,
ctx
);
// Check which operations failed
if (!did_registry::is_batch_fully_successful(&results)) {
let failures = did_registry::get_batch_failures(&results);
// failures = [2] - indicates index 2 failed (duplicate name)
let success_count = did_registry::count_batch_successes(&results);
// success_count = 2 out of 3 operations succeeded
}The DID registry now provides simplified, practical reverse lookup capabilities for fleet management. We focus on the essential use cases without over-engineering.
// Look up DID controller by human-readable name
let controller_opt = did_registry::get_did_controller_by_name(®istry, b"alice_device");
if (option::is_some(&controller_opt)) {
let controller = option::extract(&mut controller_opt);
// Found DID controller: 0xa11ce...
};
// Check if a DID name exists (useful for validation before registration)
let exists = did_registry::did_name_exists(®istry, b"device_name");
assert!(!exists, 1); // Ensure name is available// Find all devices owned by a specific address - essential for IoT fleet management
let alice_devices = did_registry::get_dids_by_controller(®istry, ALICE);
let device_count = vector::length(&alice_devices);
// Iterate through devices for management operations
let mut i = 0;
while (i < device_count) {
let device_id = *vector::borrow(&alice_devices, i);
// Perform fleet operations on device_id
i = i + 1;
};// Get total DID count for monitoring and dashboards
let total_devices = did_registry::get_registry_stats(®istry);Design Philosophy:
- ✅ Keep it simple: Only the functions that provide real business value
- ✅ Fleet management: Essential for multi-device scenarios
- ✅ Practical use cases: No premature optimization or complex indexing
- ✅ Efficient queries: Direct lookups without scanning large datasets
The system uses standardized error codes for consistent error handling across all modules:
1: Invalid controller (unauthorized access)2: Key not found3: Key already exists4: Name already exists5: Invalid public key6: Invalid data hash7: Empty field8: Field too long9: Invalid address
10: Batch too large (max 50 operations) ✨ IMPROVED11: Batch size mismatch (input vector lengths don't match) ✨ NEW12: Batch empty (reserved for future use) ✨ NEW
20: Credential not found21: Credential already revoked ✨ IMPROVED22: Unauthorized revocation (only issuer or subject can revoke) ✨ IMPROVED23: Invalid schema24: Credential expired (reserved for future use)
30: Service not found ✨ IMPROVED31: Service already exists ✨ IMPROVED32: Invalid service type (reserved for future use)33: Invalid endpoint (reserved for future use)
40-49: Reserved for future registry-specific errors
Consistent Error Patterns:
- ✅ Standardized Error Constants: All modules use the same error codes from
identity_types - ✅ Error Code Accessor Functions: Clean API with functions like
e_invalid_controller() - ✅ Comprehensive Documentation: Every error code is documented with clear descriptions
- ✅ Semantic Error Codes: Specific errors for different contexts (service vs key vs credential)
- ✅ Future-Proof: Reserved error code ranges for expansion
Before vs After:
// ❌ Before: Inconsistent hardcoded errors
assert!(valid, 1); // What does 1 mean?
assert!(batch_size <= 50, 10); // Hardcoded values
// ✅ After: Standardized semantic errors
assert!(valid, e_invalid_controller()); // Clear meaning
assert!(batch_size <= max_batch_size(), e_batch_too_large()); // Consistent patternsThe system emits comprehensive events for all major operations with detailed change tracking:
DIDRegistered: When a new DID is registeredKeyAdded: When a key is added to a DIDKeyRevoked: When a key is revokedServiceAdded: When a service endpoint is addedServiceUpdated: When a service endpoint is updated (with old/new values)ServiceRemoved: When a service endpoint is removed
CredentialIssued: When a credential is issuedCredentialRevoked: When a credential is revoked
Note: Batch operations emit individual events for each successful operation, providing complete audit trails.
suibotics_did/
├── sources/
│ ├── identity_types.move # Core data structures & W3C DID document building
│ ├── did_registry.move # DID management, service lifecycle & batch operations
│ └── credential_registry.move # Credential management, discovery & batch operations
├── tests/
│ ├── did_registry_tests.move # DID functionality tests (17 tests)
│ ├── simple_test.move # Integration tests (6 tests)
│ ├── suibotics_core_tests.move # End-to-end tests (2 tests)
│ └── batch_operations_tests.move # Batch operations tests (6 tests) ✨ NEW
│ └── reverse_lookup_tests.move # Reverse lookup tests (6 tests) ⭐ NEW
├── Move.toml # Project configuration
├── deploy_testnet.sh # Comprehensive testnet deployment script
├── deploy_simple.sh # Simple testnet deployment script
└── README.md # This file
- Total Source Code: ~45KB across 3 modules (significant expansion for batch operations)
- Lines of Code: 1,400+ lines (includes comprehensive batch operations)
- Test Coverage: 36 comprehensive tests (6 batch + 6 reverse lookup tests)
- Production Readiness: Type-safe, well-documented, follows Sui best practices
- Batch Operations: Full fleet management capabilities with partial success handling
Two deployment scripts are provided for testnet deployment:
./deploy_testnet.shThis script provides:
- ✅ Comprehensive pre-deployment checks
- ✅ Automatic environment setup
- ✅ Gas balance verification and faucet requests
- ✅ Build and test validation
- ✅ Detailed logging and error handling
- ✅ Post-deployment verification
- ✅ Explorer links and deployment info
./deploy_simple.shThis script provides:
- ⚡ Fast deployment with minimal checks
- 🎯 Essential steps only
- 📦 Package ID extraction
- 🔗 Explorer links
- Sui CLI installed (version 1.49.1+)
- Active Sui wallet
jqinstalled for JSON parsing (optional but recommended)
If you prefer manual deployment:
# Switch to testnet
sui client switch --env testnet
# Request testnet tokens
sui client faucet
# Build and test
sui move build
sui move test
# Deploy
sui client publish --gas-budget 100000000After successful deployment, you'll receive:
- Package ID: Use this to interact with your deployed modules
- Transaction Digest: For verification on blockchain explorers
- Explorer Links: View your deployment on Sui explorers
The deployment information is automatically saved to deployment_info.json for future reference.
- ✅ DID Method Implementation
- ✅ DID Document Structure
- ✅ Verification Method Support
- ✅ Service Endpoint Management
- ✅ Controller Authorization
- ✅ Resolution Interface
- ✅ Type-Safe Dynamic Field Access
- ✅ Comprehensive Input Validation
- ✅ Access Control Enforcement
- ✅ Event Logging and Audit Trails
- ✅ Error Handling and Recovery
- ✅ Batch Operation Security (size limits, partial success)
- Ensure all tests pass:
sui move test - Follow Move coding conventions
- Add tests for new functionality
- Update documentation as needed
- Maintain type safety and validation patterns
- Test batch operations with various edge cases
[Add your license information here]