# Tutus Storage Interface ## Overview The Tutus Storage Interface provides a pluggable architecture for sovereign data storage in government blockchain deployments. Different nations have different data residency requirements, and this interface allows each deployment to choose storage backends that comply with their legal framework. ## Architecture ``` ┌─────────────────────────────────────────────────────────┐ │ Tutus Blockchain │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ Block Store │ │ State Store │ │ Oracle Data │ │ │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │ │ │ │ │ │ │ ┌──────┴────────────────┴────────────────┴──────┐ │ │ │ Storage Interface (pkg/storage) │ │ │ └──────┬────────────────┬────────────────┬──────┘ │ └─────────┼────────────────┼────────────────┼─────────────┘ │ │ │ ┌──────┴──────┐ ┌──────┴──────┐ ┌──────┴──────┐ │ NeoFS │ │ Local │ │ S3 │ │ Adapter │ │ Adapter │ │ Adapter │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ ┌──────┴──────┐ ┌──────┴──────┐ ┌──────┴──────┐ │ Private │ │ Government │ │ Sovereign │ │ NeoFS Net │ │ NAS │ │ Cloud │ └─────────────┘ └─────────────┘ └─────────────┘ ``` ## Data Sovereignty Compliance ### Why This Matters Governments deploying Tutus must comply with national data residency laws: | Jurisdiction | Law | Requirement | |-------------|-----|-------------| | European Union | GDPR | EU citizen data must remain in EU | | China | Cybersecurity Law | Critical data must be stored domestically | | Russia | Federal Law 242-FZ | Personal data of citizens stored in Russia | | India | DPDP Act 2023 | Certain data categories require local storage | | Brazil | LGPD | Similar to GDPR for Brazilian citizens | ### Compliance Strategy 1. **Choose Compliant Storage**: Select storage providers that operate within your jurisdiction 2. **Private Networks**: For NeoFS, deploy a private network within national borders 3. **Sovereign Clouds**: Use government-approved cloud providers 4. **Network Isolation**: Configure firewalls to prevent cross-border data transfer 5. **Encryption**: Enable encryption at rest and in transit ## Supported Providers ### NeoFS (Decentralized Storage) Best for: - Distributed government networks - Multi-region deployments within a country - High availability requirements ```yaml storage: provider: neofs neofs: endpoints: - "grpc://neofs-node1.gov.example:8080" - "grpc://neofs-node2.gov.example:8080" container: "7s23kG4xLmNpQ..." timeout: 30s key: "/etc/tutus/neofs.key" ``` **Sovereign Deployment**: Run your own NeoFS network within national infrastructure. Do not use the public NeoFS network for government data. ### Local Filesystem Best for: - Single-node deployments - Development and testing - Air-gapped networks - NAS/SAN-backed storage ```yaml storage: provider: local local: path: /var/lib/tutus/storage max_size: 1099511627776 # 1TB compression: true ``` ### S3-Compatible Storage Best for: - Sovereign cloud providers - Existing government cloud infrastructure - AWS GovCloud, Azure Government, etc. ```yaml storage: provider: s3 s3: endpoint: "s3.sovereign-cloud.gov.example" region: "national-1" bucket: "tutus-blocks" access_key: "${S3_ACCESS_KEY}" secret_key: "${S3_SECRET_KEY}" use_path_style: true ``` ## Interface Reference ### Provider Interface The core interface that all storage backends must implement: ```go type Provider interface { // Name returns the provider identifier Name() string // Put stores data and returns a unique identifier Put(ctx context.Context, data io.Reader, opts PutOptions) (ObjectID, error) // Get retrieves data by its identifier Get(ctx context.Context, id ObjectID) (io.ReadCloser, error) // Delete removes an object from storage Delete(ctx context.Context, id ObjectID) error // Exists checks if an object exists Exists(ctx context.Context, id ObjectID) (bool, error) // List returns objects matching the given prefix List(ctx context.Context, prefix string, opts ListOptions) ([]ObjectInfo, error) // Head retrieves object metadata without content Head(ctx context.Context, id ObjectID) (ObjectInfo, error) // Close releases resources Close() error } ``` ### BlockStorage Interface Extended interface for blockchain-specific operations: ```go type BlockStorage interface { Provider // PutBlock stores a block with its index PutBlock(ctx context.Context, index uint32, data []byte) (ObjectID, error) // GetBlock retrieves a block by its index GetBlock(ctx context.Context, index uint32) ([]byte, error) // GetBlockRange retrieves multiple blocks efficiently GetBlockRange(ctx context.Context, start, end uint32) ([][]byte, error) // GetLatestBlockIndex returns the highest block index GetLatestBlockIndex(ctx context.Context) (uint32, error) } ``` ### StateStorage Interface Extended interface for state snapshot operations: ```go type StateStorage interface { Provider // PutState stores a state snapshot at a specific height PutState(ctx context.Context, height uint32, data io.Reader) (ObjectID, error) // GetState retrieves the state snapshot for a given height GetState(ctx context.Context, height uint32) (io.ReadCloser, error) // GetLatestState returns the most recent state snapshot GetLatestState(ctx context.Context) (height uint32, data io.ReadCloser, err error) } ``` ## Usage Examples ### Basic Usage ```go import ( "github.com/tutus-one/tutus-chain/pkg/storage" "github.com/tutus-one/tutus-chain/pkg/storage/local" ) // Create provider provider, err := local.New(local.Config{ Path: "/var/lib/tutus/storage", }) if err != nil { log.Fatal(err) } defer provider.Close() // Store data id, err := provider.Put(ctx, strings.NewReader("block data"), storage.PutOptions{ ContentType: "application/octet-stream", Attributes: map[string]string{ "block_index": "12345", }, }) // Retrieve data reader, err := provider.Get(ctx, id) if err != nil { log.Fatal(err) } defer reader.Close() data, _ := io.ReadAll(reader) ``` ### Registry Pattern ```go // Create registry with multiple providers registry := storage.NewRegistry() registry.Register(neofsAdapter) registry.Register(localAdapter) // Get provider by name provider, ok := registry.Get("neofs") if !ok { // Fallback to local provider, _ = registry.Get("local") } ``` ## Implementing Custom Providers To add support for a new storage backend: 1. Create a new package under `pkg/storage/` 2. Implement the `storage.Provider` interface 3. Optionally implement `BlockStorage` or `StateStorage` 4. Add configuration to `storage.Config` Example structure: ``` pkg/storage/ ├── storage.go # Core interfaces ├── config.go # Configuration types ├── errors.go # Error definitions ├── neofs/ # NeoFS adapter │ └── adapter.go ├── local/ # Local filesystem adapter │ └── adapter.go └── mycloud/ # Custom provider └── adapter.go ``` ## Security Considerations 1. **Encryption at Rest**: Enable storage-level encryption for sensitive data 2. **Access Control**: Use provider-specific ACLs to restrict access 3. **Audit Logging**: Enable logging for all storage operations 4. **Key Management**: Use HSMs or secure key storage for encryption keys 5. **Network Security**: Encrypt all traffic between nodes and storage ## Performance Tuning ### NeoFS - Increase `timeout` for large objects - Use multiple endpoints for load balancing - Configure appropriate `session_expiration_duration` ### Local Storage - Use SSDs for best performance - Enable compression for storage efficiency - Set appropriate `max_size` to prevent disk exhaustion ### S3 - Enable transfer acceleration where available - Use regional endpoints for lower latency - Configure appropriate retry policies ## Monitoring Key metrics to monitor: | Metric | Description | |--------|-------------| | `storage_put_duration_seconds` | Time to store objects | | `storage_get_duration_seconds` | Time to retrieve objects | | `storage_errors_total` | Total storage errors by type | | `storage_objects_total` | Total objects stored | | `storage_bytes_total` | Total bytes stored | ## Troubleshooting ### Common Issues **ErrNotFound** - Object was deleted or never stored - Check object ID format **ErrConnectionFailed** - Storage backend is unreachable - Check network connectivity and firewall rules **ErrQuotaExceeded** - Storage limits reached - Increase quota or clean up old data **ErrTimeout** - Operation took too long - Increase timeout or check network latency